{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对应 `tf.keras` 的01~02章节"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T01:29:26.541293Z",
     "start_time": "2025-01-15T01:29:18.919142Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "data": {
      "text/plain": "784"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "28*28"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-17T03:06:30.417590400Z",
     "start_time": "2024-07-17T03:06:30.410095400Z"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 数据准备1，为了看灰度图片"
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:06.382299Z",
     "start_time": "2025-01-15T02:13:06.356673Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torchvision import transforms\n",
    "\n",
    "\n",
    "# 定义数据集的变换\n",
    "transform = transforms.Compose([\n",
    "])\n",
    "# fashion_mnist图像分类数据集，衣服分类，60000张训练图片，10000张测试图片\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 当然也可以用 torch.utils.data.Dataset 实现人为划分"
   ],
   "outputs": [],
   "execution_count": 10
  },
  {
   "cell_type": "code",
   "source": [
    "type(train_ds)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:08.733474Z",
     "start_time": "2025-01-15T02:13:08.730609Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torchvision.datasets.mnist.FashionMNIST"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "source": [
    "len(train_ds)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:11.750565Z",
     "start_time": "2025-01-15T02:13:11.747604Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "60000"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "source": [
    "type(train_ds[0])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:13.594811Z",
     "start_time": "2025-01-15T02:13:13.591838Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tuple"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 13
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:21.371514Z",
     "start_time": "2025-01-15T02:13:21.368524Z"
    }
   },
   "source": [
    "# 通过id取数据，取到的是一个元祖,是第一个样本,在训练时，把特征和标签分开\n",
    "img, label = train_ds[0]"
   ],
   "outputs": [],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:23.638090Z",
     "start_time": "2025-01-15T02:13:23.635545Z"
    }
   },
   "cell_type": "code",
   "source": "type(img) #tensor中文是 张量,和numpy的ndarray类似",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PIL.Image.Image"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 16
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-14T08:16:50.708516Z",
     "start_time": "2025-01-14T08:16:50.682030Z"
    }
   },
   "cell_type": "code",
   "source": "img",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<PIL.Image.Image image mode=L size=28x28>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAACS0lEQVR4AWKgA2BkYOD1ZGBgZAHZxcjIAKZBbBBm+quS8v3rj1N/GBiZGP8wMKNIMv91cnnCzuU65+X/vww8/76hSP5iMFVgZtpp2HXm8nUz02PHGUHGQTHjf9cugd//GE7f+cUo8ft0yDSEJCMDw/8TCgyMf34x/Ph3/vYfT0VphLH/GRgY3kt+Z2fl+cH5z8aSSWwHqmsZuJiZvn18p/CPkYnr7z9ZBiaofQwMjMwMPFI/frH++sr/j537K9sldhOE5H9mhnBJJg4Gbtlf7L//cQhvusaCkGT5xXDlBxsXl6rSD2Yunr9PoraeYAGZx8T4+x/DHwaGbV+/s/1/zczxm+H3P2a9jwxMDMz///z6+Y+BwW7ime9v//z78/XrXw6GbwxsX4NAYc3AICSlJhmk/oPpN+czVjbhX1zHeOz+fWR9qcnIYNkkKvCX+cMfrl+M36+HneEVVGC4x/v5GycPHxcj83GpP3+/MTB/Z2DgF0lwy3z24/49VeFfrLxsf+UBY0xqv8vDw87Ayv/4mSiTRACHIrexMdMvJjYGRlYLlpeP+X485mHje/eQ5/uPP+svKwj9+vD77y/Wf4xsaixP/z/mFvnw5jULOysHL9Mbza+P37O/+f3nN6fERwOWC+sTn937wcPGwcb88+//by/+/WX5wfPrw4fffxRfMjIweBWLv/7wl5mNhZnxPysrGysjA+NLBrZ/EpfCGJn+MTA4tYnxMzGz/GV8+f/pvy/MDP9/f2Paff0YJBAYGBg0RN/LPPx1Fx5HFDIAaCTYdiCc4RIAAAAASUVORK5CYII=",
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAcABwBAREA/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/APn+tbw1oNx4m8QWmkWx2yXD4LkZCADJJ+gFbviL4a63oc7COE3MW4hdn38duD976jNc9daDqllIsc9lKrMu4YGeMkdR7gj8KzcV7H8BtEvV16+1iWCeG1Wz8mOV02pIzupwCeuAp6Z98cZ90aIzLIlw0c0ZJ4KgjHoeOa+evjS9n/wnMcNxBPCYLKONFhA2FNzMpGenDcgd816V4K03wefC+m3NlpVhP+5QSXBiR5fMx825iMg5zwce3FdbOzTwgW90lu6uCm8eYrL02soIyCPQgggEdMGQ3cluiPNK0rJwrRQBNueuMkt+teNfGKxsdY8WWdxNqcNo66eieXMwVsb5DnH415Hp2rajpE5n02/urOUjBe3laMkehIPIrVm8eeLrhNknibVivoLtx/I1UPinxC3XXtUP1vJP8ay5JZJpGkldnduSzHJP41//2Q=="
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 16
  },
  {
   "cell_type": "code",
   "source": [
    "type(img)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:39.174388Z",
     "start_time": "2025-01-15T02:13:39.171790Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PIL.Image.Image"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 18
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "9"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "label"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-17T03:06:33.599820400Z",
     "start_time": "2024-07-17T03:06:33.545914600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "source": [
    "# 显示图片，这里需要把transforms.ToTensor(),进行归一化注释掉，否则是不行的\n",
    "def show_img_content(img):\n",
    "    from PIL import Image\n",
    "\n",
    "    # 打开一个图像文件\n",
    "    # img = Image.open(img)\n",
    "\n",
    "\n",
    "    print(\"图像大小:\", img.size)\n",
    "    print(\"图像模式:\", img.mode)\n",
    "\n",
    "\n",
    "    # 如果图像是单通道的，比如灰度图，你可以这样获取像素值列表：\n",
    "    if img.mode == 'L':\n",
    "        pixel_values = list(img.getdata())\n",
    "        print(pixel_values)\n",
    "show_img_content(img) #这里必须把上面的 transforms.ToTensor(), # 转换为tensor，进行归一化注释掉，否则是不行的"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:50.749937Z",
     "start_time": "2025-01-15T02:13:50.747354Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "图像大小: (28, 28)\n",
      "图像模式: L\n",
      "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 13, 73, 0, 0, 1, 4, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 36, 136, 127, 62, 54, 0, 0, 0, 1, 3, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 102, 204, 176, 134, 144, 123, 23, 0, 0, 0, 0, 12, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 236, 207, 178, 107, 156, 161, 109, 64, 23, 77, 130, 72, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 69, 207, 223, 218, 216, 216, 163, 127, 121, 122, 146, 141, 88, 172, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 200, 232, 232, 233, 229, 223, 223, 215, 213, 164, 127, 123, 196, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 225, 216, 223, 228, 235, 227, 224, 222, 224, 221, 223, 245, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 228, 218, 213, 198, 180, 212, 210, 211, 213, 223, 220, 243, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 12, 219, 220, 212, 218, 192, 169, 227, 208, 218, 224, 212, 226, 197, 209, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 99, 244, 222, 220, 218, 203, 198, 221, 215, 213, 222, 220, 245, 119, 167, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 55, 236, 228, 230, 228, 240, 232, 213, 218, 223, 234, 217, 217, 209, 92, 0, 0, 0, 1, 4, 6, 7, 2, 0, 0, 0, 0, 0, 237, 226, 217, 223, 222, 219, 222, 221, 216, 223, 229, 215, 218, 255, 77, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 62, 145, 204, 228, 207, 213, 221, 218, 208, 211, 218, 224, 223, 219, 215, 224, 244, 159, 0, 0, 0, 0, 0, 18, 44, 82, 107, 189, 228, 220, 222, 217, 226, 200, 205, 211, 230, 224, 234, 176, 188, 250, 248, 233, 238, 215, 0, 0, 57, 187, 208, 224, 221, 224, 208, 204, 214, 208, 209, 200, 159, 245, 193, 206, 223, 255, 255, 221, 234, 221, 211, 220, 232, 246, 0, 3, 202, 228, 224, 221, 211, 211, 214, 205, 205, 205, 220, 240, 80, 150, 255, 229, 221, 188, 154, 191, 210, 204, 209, 222, 228, 225, 0, 98, 233, 198, 210, 222, 229, 229, 234, 249, 220, 194, 215, 217, 241, 65, 73, 106, 117, 168, 219, 221, 215, 217, 223, 223, 224, 229, 29, 75, 204, 212, 204, 193, 205, 211, 225, 216, 185, 197, 206, 198, 213, 240, 195, 227, 245, 239, 223, 218, 212, 209, 222, 220, 221, 230, 67, 48, 203, 183, 194, 213, 197, 185, 190, 194, 192, 202, 214, 219, 221, 220, 236, 225, 216, 199, 206, 186, 181, 177, 172, 181, 205, 206, 115, 0, 122, 219, 193, 179, 171, 183, 196, 204, 210, 213, 207, 211, 210, 200, 196, 194, 191, 195, 191, 198, 192, 176, 156, 167, 177, 210, 92, 0, 0, 74, 189, 212, 191, 175, 172, 175, 181, 185, 188, 189, 188, 193, 198, 204, 209, 210, 210, 211, 188, 188, 194, 192, 216, 170, 0, 2, 0, 0, 0, 66, 200, 222, 237, 239, 242, 246, 243, 244, 221, 220, 193, 191, 179, 182, 182, 181, 176, 166, 168, 99, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 61, 44, 72, 41, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "cell_type": "code",
   "source": [
    "#这个代码必须是注释了上面的 transforms.ToTensor()才能够运行的\n",
    "def show_single_image(img_arr):\n",
    "    plt.imshow(img_arr, cmap=\"binary\") # 显示图片\n",
    "    plt.colorbar() # 显示颜色条\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "show_single_image(img)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:13:52.822873Z",
     "start_time": "2025-01-15T02:13:52.763338Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfAAAAGdCAYAAADtxiFiAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAALUJJREFUeJzt3QtsVNed+PHf4eEXYIN52KYYyiMJJDzSJbxCwhJgeVVsIGgVEraCCoFCDSpYCVkqXnlI3tKoiZIloHZTSHZxmqAGUFDllkAwRYE0cRdRkpRgCsUIbAgVNk9j7PnrnHTm7wEDPtfjsY/P9yNdDTNzj+dyPZ7f/M459/xUKBQKCQAAcEqrpj4AAABgjwAOAICDCOAAADiIAA4AgIMI4AAAOIgADgCAgwjgAAA4iAAOAICD2kgzU1NTI6dPn5YOHTqIUqqpDwcAYEmvD3bx4kXp3r27tGrVeHnitWvX5Pr16w3+OQkJCZKUlCSuaXYBXAfv7Ozspj4MAEADlZSUSI8ePRoteCcnJ8fkZ2VmZsrx48edC+LNLoDrzDv8i09NTW3qwwEAWKqoqDCJWPjzvDFcj0HmHVZaWmp+HgH8H9atWyc/+9nPzIkZMmSIvPHGGzJ8+PC7tgt3m+vgTQAHAHfFaxhUNeB1XC4H0iiDE++9957k5ubK6tWr5U9/+pMJ4JMmTZKzZ882xssBADyllGrwZiMvL0+GDRtmehe6desm06dPlyNHjkTtM3bs2Fte45lnnona5+TJk/L9739fUlJSzM957rnn5MaNG00fwH/+85/L/Pnz5Yc//KHcf//9smHDBnOQv/rVrxrj5QAAnlJxDuCFhYWSk5MjBw4ckJ07d0pVVZVMnDhRLl++HLWfjoFnzpyJbGvXro08V11dbYK37rb/5JNP5O2335ZNmzbJqlWrmrYLXR9QUVGRLF++PPKYnoU4YcIE2b9//y37V1ZWmq322AkAAPWhAgThhigoKIi6rwOvzqB13BszZkzkcZ206slxdfn9738vX375pXz00UeSkZEhDz74oLz00kvy/PPPy5o1a8ys+CbJwL/55hvz7UIfVG36vh4Pr6s7Ii0tLbIxAx0AEG8VFRVRW+3E8k7Ky8vNbXp6etTjmzdvli5dusjAgQNNQnvlypXIczqZHTRoUFSc1MPM+nW/+OILdxZy0f8xfQLCm559DgBAPLvQs7Ozo5JJnVzWZ92SJUuWyOjRo02gDnv66aflf//3f+Xjjz82Me5//ud/5N///d8jz+tktq4kN/xck3Wh628crVu3lrKysqjH9f26uhMSExPNBgBAU3Whl9x06XJ94pIeCz98+LDs27cv6vEFCxZE/q0z7aysLBk/frwcO3ZM+vbtK7ES8wxc990PHTpUdu3aFfUtRd8fNWpUrF8OAIAGC1+6HN7uFsAXLVokO3bsMFn23RarGTFihLktLi42tzqZrSvJDT/XpF3o+hKyX/7yl2Zm3VdffSULFy40M/T0rHQAAFydhR4KhUzw3rp1q+zevVt69+591zYHDx40tzoT13Qy++c//znq0mo9o11/cdBXbjXpQi5PPvmknDt3zkyJ1/35eoadnrl3c58/AAAuzULPycmR/Px82b59u7kWPDxmrcfN9dKuuptcPz916lTp3LmzHDp0SJYuXWpmqA8ePNjsqy8704H6Bz/4gbm8TP+MFStWmJ9tM6SsQs1sGRo9C0+fCD2hjZXYAMA98fgcr/jHa+iA19CV2PSM8/oe6+1ea+PGjTJ37lwzlq4nrOmxcd3zrCfHzZgxwwTo2j//b3/7m+md3rNnj7Rr107mzJkj//mf/ylt2tQ/ryaAAwCcDeBJSUkNDuC6MIqLMafZFTMBAKC5dqE3J01+HTgAALBHBg4AcJbyOAMngAMAnKUI4AAAuEd5HMAZAwcAwEFk4AAAZymPM3ACOADAWcrjAE4XOgAADiIDBwA4S3mcgRPAAQDOUh4HcLrQAQBwEBk4AMBZyuMMnAAOAHCaamA1MlfRhQ4AgIPIwAEA3nahK4e73wngAABnKQI4AADuUR4HcMbAAQBwEBk4AMBZyuMMnAAOAHCW8jiA04UOAICDyMABAM5SHmfgBHAAgLOUxwGcLnQAABxEBg7UEmRd5Hh9g7948aJ1m3379gV6rSlTpkhzPd/V1dXWbdq0aXkfdfFcw7s5Z6nK4wy85b2rAQDeUB4HcLrQAQBwEBk4AMBZyuMMnAAOAHCWIoADAOAe5XEAZwwcAAAHkYEDAJylPM7ACeAAAGcpjwM4XegAADiIDBwA4CzlcQZOAAcAOEt5HMDpQgcAwEFk4EAtNTU11m1at25t3aa4uNi6zX//939bt0lOTpYg2rVrZ90mKSnJus3w4cObdWGSIAVDgryHgrxOPM+DbQGZIAVnglIeZ+AEcACA05TDQbgh6EIHAMBBZOAAAGcputABAHCPIoADAOAe5XEAZwwcAAAHkYEDAJylPM7ACeAAAGcpjwM4XegAADiIDBwA4CzlcQZOAAcAOEt5HMDpQgcAwEFk4EADizAEKWaye/du6zY7d+60bpOdnS1BVFZWWre5cuWKdZvf//731m3mz59v3SYjI0PilZ0FeT8EcenSpUDtWrWyz9tSUlKa5TnwPQMngAMAnKU8DuB0oQMA4KCYB/A1a9ZEvhGFt/79+8f6ZQAAkJvjTZDNVY3Shf7AAw/IRx991CSF5wEA/lAed6E3SmTVATszM7MxfjQAABE+B/BGGQM/evSodO/eXfr06SOzZ8+WkydP3nG2a0VFRdQGAADiHMBHjBghmzZtkoKCAlm/fr0cP35cHn30Ubl48WKd++fl5UlaWlpkC3rZCwDAP8rjMfCYB/ApU6bIv/3bv8ngwYNl0qRJ8tvf/lYuXLgg77//fp37L1++XMrLyyNbSUlJrA8JANBCKY8DeKPPLuvYsaPce++9UlxcXOfziYmJZgMAAM3oOnC9WtCxY8ckKyursV8KAOAZFecMXA/7Dhs2TDp06CDdunWT6dOny5EjR6L2uXbtmuTk5Ejnzp2lffv2MnPmTCkrK4vaR88N+/73v29WudM/57nnnpMbN240bQB/9tlnpbCwUE6cOCGffPKJzJgxwyyr99RTT8X6pQAAnlNxDuA6vungfODAAbO8cVVVlUycOFEuX74c2Wfp0qXy4YcfypYtW8z+p0+flieeeCJqyWYdvK9fv27i5Ntvv23mjq1atappu9BPnTplgvX58+ela9eu8sgjj5j/qP43AAAuKygoiLqvA6/OoIuKimTMmDFmLtdbb70l+fn5Mm7cOLPPxo0bZcCAASYWjhw50tQA+PLLL816KXqd/gcffFBeeuklef75581iaAkJCU0TwH/961/H+kcCcVPfP5yG+uyzz6zb6F4tWzU1NdZtgrbTWYit//u//7Nus2zZMus2Dz30kAQxaNAg6zb6g9rWH//4x7i8h7SHH37Yus2oUaOs9o/n5cAqRteB33zM9Z2fpQO2lp6ebm51INdZ+YQJEyL76NVIe/bsKfv37zcBXN/q91btIjt60vfChQvliy++kO9973v1OnbWQgcAOE3FoPtcX8Jc+5JmPdZdny+6S5YskdGjR8vAgQPNY6WlpSYR0BO4a9PBWj8X3ufmCnnh++F96oM1TgEA3ispKZHU1NTI/fpk33os/PDhw7Jv3z5pCgRwAICzVIy60HXwrh3A72bRokWyY8cO2bt3r/To0SPyuF5GXE9O0+uf1M7C9Sz08BLj+vbmYZPwLHWbZcjpQgcAOEvFeRZ6KBQywXvr1q2ye/du6d27d9TzQ4cOlbZt28quXbsij+nLzPRlY+G5BPr2z3/+s5w9ezayj57Rrr9A3H///fU+FjJwAICzVJyLmehucz3DfPv27eZa8PCYtR43T05ONrfz5s2T3NxcM7FNB+XFixeboK0nsIUnfOpA/YMf/EDWrl1rfsaKFSvMz7ZZ2IwADgBAPekaH9rYsWOjHteXis2dO9f8+9VXX5VWrVqZBVx0wS49w/zNN9+M7KvXRtHd73rWuQ7s7dq1kzlz5siLL74oNgjgAABnqThn4LoL/W6SkpJk3bp1ZrudXr16mVohDUEABwA4S1EPHAAAuIQMHADgLOVxBk4ABwA4S3kcwOlCBwDAQWTgaJHqM1M0Vt/G9QIMtj7//HPrNjarRIXVLnFo4+uvv45LG11X2Va/fv2s21y6dEmC0KUebX3wwQfWbdq0sf8oHj58uATxy1/+stGL/AR93wWhPM7ACeAAAGcpjwM4XegAADiIDBwA4CzlcQZOAAcAOEsRwAEAcI/yOIAzBg4AgIPIwAEAzlIeZ+AEcACAs5THAZwudAAAHEQGDgBwlvI4AyeAAwCcpTwO4HShAwDgIDJwAICzlMcZOAEcTlQJa85Wrlxp3ebMmTMSD1euXAnUrnXr1tZtEhMTrdvs27cvLpXcgn5I/9M//ZN1m3vuuScu5/u//uu/JIi//vWv1m1+85vfWO1fUVEh8aQcDsINQRc6AAAOIgMHADhL0YUOAIB7FAEcAAD3KI8DOGPgAAA4iAwcAOAs5XEGTgAHADhLeRzA6UIHAMBBZOAAAGcpjzNwAjgAwFnK4wBOFzoAAA4iAwcAOEt5nIETwBFXLv+x3E6nTp3iUswkOTnZuk1lZaUEUVVVZd3m0qVL1m2SkpKs21y9ejVu77sgxVY++eSTuBT5KSsrkyAmT54sLYnyOIDThQ4AgIPIwAEAzlIeZ+AEcACAsxQBHAAA9yiPAzhj4AAAOIgMHADgLOVxBk4ABwA4S3kcwOlCBwDAQWTgAABnKY8zcAI4AMBZyuMAThc6AAAOIgMHADhLeZyBE8CBBrpy5Yp1m+rqaus2NTU1cSmAomVmZlq36dy5s3WbEydOWLdp1apVXIqFBP09BSm2EuT/1Lp1awni1KlT0pIojwM4XegAADiIDBwA4DTlcBYd1wx87969Mm3aNOnevbs5adu2bbulq2rVqlWSlZVluu8mTJggR48ejeUxAwAQ1YXekM2bAH758mUZMmSIrFu3rs7n165dK6+//rps2LBBPv30U2nXrp1MmjRJrl27FovjBQAgwucAbt2FPmXKFLPVRWffr732mqxYsUIef/xx89g777wjGRkZJlOfNWtWw48YAADEdhLb8ePHpbS01HSbh6WlpcmIESNk//79dbaprKyUioqKqA0AgPpQHmfgMQ3gOnhrOuOuTd8PP3ezvLw8E+TDW3Z2diwPCQDQgikCeNNZvny5lJeXR7aSkpKmPiQAAPy6jCy8+ENZWZmZhR6m7z/44IN1tklMTDQbAAC2FAu5xEbv3r1NEN+1a1fkMT2mrWejjxo1KpYvBQCA+NyFbp2BX7p0SYqLi6Mmrh08eFDS09OlZ8+esmTJEnn55ZflnnvuMQF95cqV5prx6dOnx/rYAQDwlnUA//zzz+Wxxx6L3M/NzTW3c+bMkU2bNsmyZcvMteILFiyQCxcuyCOPPCIFBQWSlJQU2yMHAHhPedyFbh3Ax44de8fCAPpkvPjii2YDYlFUIkgRj6CFHnQPk63Tp09btwky7yMhIcG6zfXr1yWIIMenF22ypSeuxqNoSpCCM0HPX/v27a3bBLl8dtCgQRKETrCCJG6N/XcUlCKAAwDgHuVxAG/yy8gAAIA9MnAAgLMUGTgAAO5RTXAZ2d2qcs6dO/eW15g8eXLUPn//+99l9uzZkpqaKh07dpR58+ZZzx0ggAMAEMOqnJoO2GfOnIls7777btTzOnh/8cUXsnPnTtmxY4f5UqCv3rJBFzoAwFmqCbrQ71SVs/aVHOHVSW/21VdfmcurP/vsM3nooYfMY2+88YZMnTpVXnnlFZPZ1wcZOABAfO9Cr7ipKqaulNkQe/bskW7dusl9990nCxculPPnz0ee09U5dbd5OHhruopnq1atzMql9UUABwB4Lzs7O6oypq6UGZTuPn/nnXfMsuI//elPpbCw0GTs1dXV5nldnVMH99ratGljVjS9XeXOutCFDgAQ37vQS0pKzISysIYU2Zo1a1bUgjuDBw+Wvn37mqx8/PjxEitk4AAA8b0LPTU1NWqLZZXMPn36SJcuXSJ1RPTY+NmzZ6P2uXHjhpmZfrtx87oQwAEAaESnTp0yY+DhMtu6OqeuFVJUVBTZZ/fu3WbZ6BEjRtT759KFDgBwlmqCWeh3qsqptxdeeEFmzpxpsuljx46ZIl/9+vWTSZMmmf0HDBhgxsnnz58vGzZskKqqKlm0aJHpeq/vDHSNDBwA4CzVBAu56OIu3/ve98wWrsqp/71q1SpTSOnQoUPyr//6r3LvvfeaBVqGDh0qf/jDH6K65Tdv3iz9+/c3Y+L68jFdufMXv/iF1XGQgSOugvyxhGduxqMa2XvvvWfdRi/SYKtr167Wba5evRq38xCkYtXJkyet27Rt29a6TZDLe/QM3yB0ZhSP39M333xj3SYnJ0eC0JmiLT0+29h/sw2h4rwc6t2qcv7ud7+768/QmXp+fn6DjoMMHAAAB5GBAwCcpTwuZkIABwA4S3kcwOlCBwDAQWTgAABnKY8zcAI4AMBZyuMAThc6AAAOIgMHADhLeZyBE8ABAM5SHgdwutABAHAQGTgAwFnK4wycAA4AcJYigAPxYVsUQUtISJB4GThwoHWb2hWGGrNIRjyLupw9e9a6TVJSknUbXdAhHu+hIOc7aFGXTp06WbfJzs62bhO0EMZzzz1n3WbkyJFW+1dUVEi8KI8DOGPgAAA4iAwcAOAs5XEGTgAHADhLeRzA6UIHAMBBZOAAAGcpjzNwAjgAwFnK4wBOFzoAAA4iAwcAOEt5nIETwAEAzlIeB3C60AEAcBAZOADAWcrjDJwADgBwliKA+ykUCgVqF6SoRE1NTVyOr23bttZtWrWK30hKmzbN+y03ZcoU6zbt27e3bpOcnGzd5vr16xIvXbt2jUuRkWvXrjXr4jZB3q9B/p6CfKYcOnRIgkhLS5OWRjkchBuCMXAAABzUvNMhAADuQNGFDgCAe5THAZwudAAAHEQGDgBwlvI4AyeAAwCcpTwO4HShAwDgIDJwAICzlMcZOAEcAOAs5XEApwsdAAAHkYEDAJylPM7ACeAAAGcpArj7ghQDaN26dYssyNGc7d2717rNb37zG+s2+/btkyBSUlKs23Tu3Nm6TWVlZVw+aIK+V4OchyB/g0HOQ5ACKEE/pNu1ayfxEKRQTdBj++CDD6zbTJs2TZor5XEAZwwcAAAHkUoCAJylyMDtukB1d0r37t3Nf3zbtm1Rz8+dOzdyQsPb5MmTY3nMAAAYN8ebIJs3Afzy5csyZMgQWbdu3W330QH7zJkzke3dd99t6HECAICGdKFPmTLFbHeSmJgomZmZtj8aAAArii702NqzZ49069ZN7rvvPlm4cKGcP3/+jrNQKyoqojYAAOpD0YUeO7r7/J133pFdu3bJT3/6UyksLDQZ++0uMcnLy5O0tLTIlp2dHetDAgCgxYn5LPRZs2ZF/j1o0CAZPHiw9O3b12Tl48ePv2X/5cuXS25ubuS+zsAJ4gCA+lB0oTeePn36SJcuXaS4uPi24+WpqalRGwAA9aHoQm88p06dMmPgWVlZjf1SAAB4w7oL/dKlS1HZ9PHjx+XgwYOSnp5uthdeeEFmzpxpZqEfO3ZMli1bJv369ZNJkybF+tgBAJ5THnehWwfwzz//XB577LHI/fD49Zw5c2T9+vVy6NAhefvtt+XChQtmsZeJEyfKSy+9ZLrKAQCIJUUAr7+xY8dKKBS67fO/+93vpCkELUwSL3//+9+t25w+fdq6zddffx2X1wlaFCHI8QX58ldTUyNBBCkQcafLJG9Hf7m1lZSUZN2mqqpKgigrK4vL7+nKlSvWbR5++GHrNhcvXpQg/vCHP1i3adXKfmRSX4Fjq23bthLEgQMHpKVRDgfhhqCYCQAADqKYCQDAWYoudAAA3KM8DuB0oQMA4CAycACAs5THGTgBHADgLOVxAKcLHQAAB5GBAwCcpTzOwAngAABnKY8DOF3oAABY2Lt3r0ybNs2sqKi/AGzbti3qeb1a6apVq0wRr+TkZJkwYYIcPXr0ltU5Z8+ebSpwduzYUebNm2dqjdgggAMAnKWaoJzo5cuXZciQIbJu3bo6n1+7dq28/vrrsmHDBvn000/NEs26oNe1a9ci++jg/cUXX8jOnTtlx44d5kvBggULrI6DLnQAgLNUE3ShT5kyxWx10dn3a6+9JitWrJDHH3/cPPbOO+9IRkaGydRnzZolX331lRQUFMhnn30mDz30kNnnjTfekKlTp8orr7xS71oJZOAAAPE9A6+oqIjaKisrAx2PLrFdWlpqus1rF6sZMWKE7N+/39zXt7rbPBy8Nb2/LoSjM3bvMvDwibGhxyiCOHfunHUbXV41HlWNglTh0m+keFWA69ChQ1yqXN2pYt6d6PGqeFTHeu+996zbDBs2zLqN/iAKIkjlsxMnTkg86JLFtmzHFsN69OgRl4p2Qaqy6W7cIOL1e3JNdnZ21P3Vq1fLmjVrrH+ODt6azrhr0/fDz+nbbt26RT3fpk0bSU9Pj+zjVQAHAPhHxagLvaSkxEwoa0jiEG90oQMAxPcu9NTU1KgtaADPzMw0t2VlZVGP6/vh5/Tt2bNno56/ceOGmZke3qc+COAAAMRI7969TRDetWtX1FCWHtseNWqUua9v9bBqUVFRZJ/du3ebIVA9Vl5fdKEDAJylmmAWup5TUVxcHDVx7eDBg2YMu2fPnrJkyRJ5+eWX5Z577jEBfeXKlWZm+fTp083+AwYMkMmTJ8v8+fPNpWZVVVWyaNEiM0O9vjPQNQI4AMBZqgkC+Oeffy6PPfZY5H5ubq65nTNnjmzatEmWLVtmJhnq67p1pv3II4+Yy8ZqTw7dvHmzCdrjx483E5Znzpxprh23QQAHAMDC2LFj73ili/5S8OKLL5rtdnS2np+fLw1BAAcAOEt5vBY6ARwA4CzlcQBnFjoAAA4iAwcAOEt5nIETwAEAzlIEcAAA3KQcDsItMoBXV1ebrb5+/OMfW7/G6dOnJQi96Hw8CpMEKYoQRNCqO0EKfwRpE0R5eXmgdn/729+s2/zHf/xHXM7D+vXrrdtkZWVJvIqZjBs3zrpN3759rdscPXrUus358+cliLZt21q30UtixqMIUZDPIe3mIhpwV7MN4AAA3I2iCx0AAPcojwM4l5EBAOAgMnAAgLOUxxk4ARwA4CzlcQCnCx0AAAeRgQMAnKU8zsAJ4AAAZymPAzhd6AAAOIgMHADgLOVxBk4ABwA4SxHAAQBwjyKANz/5+flWBR+CFKHo06ePBHH58mXrNhcvXoxbAYZ4FF8IWjCkR48e1m2+853vWLe5evWqBJGRkWHdZs6cOdZttm3bZt1m2rRp1m2OHz8u8XqPFxUVWbf5+OOPrdvYFDkKS0xMlHgV+rl+/brEQ9BiJkGOr6SkpNE/79CCAjgAAHejyMABAHCP8jiAcxkZAAAOIgMHADhLeZyBE8ABAM5SHgdwutABAHAQGTgAwFnK4wycAA4AcJbyOIDThQ4AgIPIwAEAzlIeZ+AEcACAsxQBHAAA9ygCePPTtWtXSUlJadQiGUEX3A9SGKFnz55xOb6qqirrNhUVFRJEenq6dZtevXrF5TwkJSVZtwnarnXr1tZtZsyYYd1m0KBB1m1OnDghQQQppBPk76Jjx47Wbdq2bRuX35GWkJAQl2IhrVrZT0cKhULWbYK2+/rrrxu9GA5aUAAHAKClZ9ENQQAHADhLedyFbtVvk5eXJ8OGDZMOHTpIt27dZPr06XLkyJGofa5duyY5OTnSuXNnad++vcycOVPKyspifdwAAHjNKoAXFhaa4HzgwAHZuXOnGW+dOHFi1HjH0qVL5cMPP5QtW7aY/U+fPi1PPPFEYxw7AMBz6h8ZeEM2L7rQCwoKou5v2rTJZOJFRUUyZswYKS8vl7feekvy8/Nl3LhxZp+NGzfKgAEDTNAfOXJkbI8eAOA1RRd6MDpg156NrAO5zsonTJgQ2ad///5mBvb+/fvr/BmVlZVmFnTtDQAANFIAr6mpkSVLlsjo0aNl4MCB5rHS0lJz2cXNl4ZkZGSY5243rp6WlhbZsrOzgx4SAMAzyuMu9MABXI+FHz58WH7961836ACWL19uMvnwVlJS0qCfBwDwh/I4gAe6jGzRokWyY8cO2bt3b9QCKpmZmWYRgwsXLkRl4XoWun7udos/BFkAAgAAn7WyXcFHB++tW7fK7t27pXfv3lHPDx061KyStGvXrshj+jKzkydPyqhRo2J31AAACBm4Vbe5nmG+fft2cy14eFxbj10nJyeb23nz5klubq6Z2JaamiqLFy82wZsZ6ACAWFMez0K3CuDr1683t2PHjo16XF8qNnfuXPPvV1991azrqxdw0TPMJ02aJG+++WYsjxkAAIMAHsNF8HUxiHXr1pmtIbp3725WcmvMYgBBZ7wHWaj/3LlzcSn0oIvAxKONduPGDes2+ktdPF5HrwgYxKVLl6zbVFdXW7fRKxXa+vLLL63b2PwNNbT4TqdOneLyewryfm3TJtiq0UEKpwR5ratXr1q3ud2VPXeje0ptHTx4MC5/f7DDWugAAGcpMnAAANyjPA7gDVqJDQAANA0ycACAs5THGTgBHADgLOVxAKcLHQAAB5GBAwCcpTzOwAngAABnKY8DOF3oAAA4iAwcAOAs5XEGTgAHADhLEcABAHCP8jiAMwYOAICDmm0GPnjwYFNPvL5mzJhh/Rq6DGrQSmm2+vbta91GV3aLRzWt69evSxBBKihVVVXFpRpZkHMX9LWCfINPSUmxbpOVlWXdJkiVPq1169ZxOXdBKu5dvHjRuk1iYqIEEeT4grRJSEiIS6U07fjx49ZtMjIyGv2zoSGUw1l0iwzgAADcjaILHQAAuIQADgBwPgNXDdhsrFmz5pb2/fv3jzx/7do1ycnJkc6dO0v79u1l5syZUlZW1gj/cwI4AMBhKs4BXHvggQfkzJkzkW3fvn2R55YuXSoffvihbNmyRQoLC+X06dPyxBNPSGNgDBwAAAtt2rSRzMzMWx4vLy+Xt956S/Lz82XcuHGRydIDBgyQAwcOyMiRIyWWyMABAOJ7Bl5RURG1VVZW3vY1jx49aq5G6tOnj8yePVtOnjxpHi8qKjJX2kyYMCGyr+5e79mzp+zfvz/m/3cCOABAfA/g2dnZkpaWFtny8vLqfL0RI0bIpk2bpKCgQNavX28uy3v00UfN5Y2lpaXmksCbLyXUl+Hp52KNLnQAgPdKSkqi1h653doBU6ZMiVqvRAf0Xr16yfvvvy/JyckST2TgAADxPQNPTU2N2uq7+I/Otu+9914pLi424+J6YawLFy5E7aNnodc1Zt5QBHAAgLNUE8xCv3n1y2PHjpmVEocOHWpWyNu1a1fk+SNHjpgx8lGjRkms0YUOAHCWivNKbM8++6xMmzbNdJvrS8RWr15tlh5+6qmnzNj5vHnzJDc3V9LT000mv3jxYhO8Yz0DXSOAAwBQT6dOnTLB+vz589K1a1d55JFHzCVi+t/aq6++amoQ6AVc9Ez2SZMmyZtvvimNQYVCoZA0I3r6vv4Wo6+nsylmEsRvf/vbQO1eeeUV6zZnz561bhN+QzR2IYWgBS9qamqs29zp0ozbqa6ujkthDS3In0OQb/9Bji9I0ZmghWqCHF+8PkqCvE63bt0kXoIU7AnyNxh0VrOeeGVLT9Bqbp/jFf94jU8++cSseNaQLvCHH344LjEn1sjAAQDOUhQzAQAALiEDBwA4S3mcgRPAAQDOUh4HcLrQAQBwEBk4AMBZyuMMnAAOAHCW8jiA04UOAICDyMABAM5SHmfgBHAAgLMUARwAAPcojwM4Y+AAADio2WbgulCGTbGMIMUApk6dat0maLvdu3dbt/nJT35i3ebEiRPWbfQi/vEqKhGkMEmQ4hBt2rRp1oUygnzr79Gjh3WbpKQkCSJIcYggv9t4SUhICNQuJSUlLkV+/uVf/sW6zYABAyQIXbijpVEOZ9EtMoADAHA3ii50AADgEjJwAICzlMcZOAEcAOAs5XEApwsdAAAHkYEDAJylPM7ACeAAAGcpjwM4XegAADiIDBwA4CzlcQZOAAcAOEsRwAEAcI/yOIAzBg4AgIOabQaui5MEKVDSXI0bN866zYEDByQe/vKXvwRqd+7cOes2nTp1sm5z6tQp6za9evWSeBW96Nu3b6DXAtBwyuMMvNkGcAAA7kZ5HMBbTooLAIBHrAJ4Xl6eDBs2TDp06GBqIE+fPl2OHDkStc/YsWMj34jC2zPPPBPr4wYAQG6ON0E2LwJ4YWGh5OTkmLHZnTt3SlVVlUycOFEuX74ctd/8+fPlzJkzkW3t2rWxPm4AAMTnAG41Bl5QUBB1f9OmTSYTLyoqkjFjxkQeT0lJkczMzNgdJQAAiN0YeHl5ublNT0+Penzz5s3SpUsXGThwoCxfvlyuXLly259RWVkpFRUVURsAAPWhyMDt1dTUyJIlS2T06NEmUIc9/fTT5hKe7t27y6FDh+T555834+QffPDBbcfVX3jhhaCHAQDwmPJ4FnrgAK7Hwg8fPiz79u2LenzBggWRfw8aNEiysrJk/PjxcuzYsTqvl9UZem5ubuS+zsCzs7ODHhYAAF4IFMAXLVokO3bskL1790qPHj3uuO+IESPMbXFxcZ0BPDEx0WwAANhSZOD1EwqFZPHixbJ161bZs2eP9O7d+65tDh48aG51Jg4AQCwpAnj9u83z8/Nl+/bt5lrw0tJS83haWpokJyebbnL9/NSpU6Vz585mDHzp0qVmhvrgwYMb6/8AAPCUIoDXz/r16yOLtdS2ceNGmTt3rllH+qOPPpLXXnvNXBuux7JnzpwpK1asiO1RAwDgOesu9DvRAVsv9gIAQLwoh7PohqCYCaR///5xbWer9mWKAFCb8rgLnWImAAA4iAwcAOAs5XEGTgAHADhLeRzA6UIHAMBBZOAAAGcpjzNwAjgAwFnK4wBOFzoAAA4iAwcAOEt5nIETwAEAzlIEcAAA3KM8DuCMgQMA4CAycACAs5THGTgBHADgLOVxAKcLHQAAB5GBAwCcpTzOwAngAABnKY8DOF3oAAA4iAwcAOAs5XEGTgAHADhLeRzA6UIHAMBBZOAAAGcpMnAAANwN4KoBWxDr1q2T7373u5KUlCQjRoyQP/7xjxJvBHAAgLNUEwTw9957T3Jzc2X16tXypz/9SYYMGSKTJk2Ss2fPSjwRwAEAsPDzn/9c5s+fLz/84Q/l/vvvlw0bNkhKSor86le/Eq/HwEOhkLmtqKho6kMBAAQQ/vwOf543posXLzZoHFu3ryvmJCYmmu1m169fl6KiIlm+fHnksVatWsmECRNk//794nUAD5/M7Ozspj4UAEADP8/T0tIa5WcnJCRIZmZmTGJF+/btb/k5unt8zZo1t+z7zTffSHV1tWRkZEQ9ru//5S9/Ea8DePfu3aWkpEQ6dOhwy7cq/Q1Jn2T9fGpqqviK8/AtzsO3OA/f4jw0n/OgM28dvPXneWNJSkqS48ePm4w4Fsd7c7ypK/tubppdANddET169LjjPvpN6fMfaBjn4Vuch29xHr7FeWge56GxMu+bg3hSUpLEU5cuXaR169ZSVlYW9bi+r3sE4olJbAAAWHTdDx06VHbt2hV5rKamxtwfNWqUeJ2BAwDQnOXm5sqcOXPkoYcekuHDh8trr70mly9fNrPS48mpAK7HJPTEAhfGJhoT5+FbnIdvcR6+xXn4Fueh8T355JNy7tw5WbVqlZSWlsqDDz4oBQUFt0xsa2wqFI95/gAAIKYYAwcAwEEEcAAAHEQABwDAQQRwAAAc5EwAbw6l25qaXtbv5io6/fv3l5Zu7969Mm3aNLOqk/4/b9u2Lep5PQ9TzwbNysqS5ORksybx0aNHxbfzMHfu3FveH5MnT5aWJC8vT4YNG2ZWauzWrZtMnz5djhw5ErXPtWvXJCcnRzp37myWyJw5c+Yti274cB7Gjh17y/vhmWeeabJjhqcBvLmUbmsOHnjgATlz5kxk27dvn7R0+vpK/TvXX+LqsnbtWnn99ddNRaBPP/1U2rVrZ94f+oPcp/Og6YBd+/3x7rvvSktSWFhogvOBAwdk586dUlVVJRMnTjTnJmzp0qXy4YcfypYtW8z+p0+flieeeEJ8Ow+arphV+/2g/1bQgoQcMHz48FBOTk7kfnV1dah79+6hvLy8kE9Wr14dGjJkSMhn+i27devWyP2amppQZmZm6Gc/+1nksQsXLoQSExND7777bsiX86DNmTMn9Pjjj4d8cvbsWXMuCgsLI7/7tm3bhrZs2RLZ56uvvjL77N+/P+TLedD++Z//OfTjH/+4SY8LjavZZ+Dh0m26W7SpS7c1B7prWHeh9unTR2bPni0nT54Un+liBnohhdrvD70Gsx5m8fH9sWfPHtOlet9998nChQvl/Pnz0pKVl5eb2/T0dHOrPyt0Nlr7/aCHmXr27Nmi3w83n4ewzZs3m7W7Bw4caMpfXrlypYmOEF6uxNacSrc1NR2UNm3aZD6cdXfYCy+8II8++qgcPnzYjIX5SAdvra73R/g5X+juc91V3Lt3bzl27Jj85Cc/kSlTppjApYsvtDR6/eklS5bI6NGjTYDS9O9cr1XdsWNHb94PdZ0H7emnn5ZevXqZL/yHDh2S559/3oyTf/DBB016vPAogOP/0x/GYYMHDzYBXf+Bvv/++zJv3rwmPTY0vVmzZkX+PWjQIPMe6du3r8nKx48fLy2NHgPWX159mAcS5DwsWLAg6v2gJ3nq94H+cqffF3Bfs+9Cb06l25obnWXce++9UlxcLL4Kvwd4f9xKD7Pov5+W+P5YtGiR7NixQz7++OOo8sP6d66H3S5cuODF++F256Eu+gu/1hLfD75q9gG8OZVua24uXbpkvk3rb9a+0t3F+oO59vujoqLCzEb3/f1x6tQpMwbekt4fev6eDlpbt26V3bt3m99/bfqzom3btlHvB91trOeKtKT3w93OQ10OHjxoblvS+8F3TnShN5fSbU3t2WefNdcB625zfWmMvqxO90489dRT0tK/qNTOGvTENf1hpCfs6MlJevzv5Zdflnvuucd8kK1cudKM++lrY305D3rTcyL0Nc/6C43+Yrds2TLp16+fuaSuJXUX5+fny/bt2828j/C4tp64qNcA0Ld6OEl/ZuhzkpqaKosXLzbBe+TIkeLLedC/f/381KlTzfXwegxcX143ZswYM7SCFiLkiDfeeCPUs2fPUEJCgrms7MCBAyHfPPnkk6GsrCxzDr7zne+Y+8XFxaGW7uOPPzaXyNy86cumwpeSrVy5MpSRkWEuHxs/fnzoyJEjIZ/Ow5UrV0ITJ04Mde3a1VxG1atXr9D8+fNDpaWloZakrv+/3jZu3BjZ5+rVq6Ef/ehHoU6dOoVSUlJCM2bMCJ05cybk03k4efJkaMyYMaH09HTzN9GvX7/Qc889FyovL2/qQ0cMUU4UAAAHNfsxcAAAcCsCOAAADiKAAwDgIAI4AAAOIoADAOAgAjgAAA4igAMA4CACOAAADiKAAwDgIAI4AAAOIoADAOAgAjgAAOKe/wc16T7a/BQ6yQAAAABJRU5ErkJggg=="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 20
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 数据准备2，为训练做准备"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:14:25.546963Z",
     "start_time": "2025-01-15T02:14:25.515199Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torchvision import transforms\n",
    "\n",
    "\n",
    "# 定义数据集的变换\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(), # 转换为tensor，进行归一化\n",
    "    # transforms.Normalize(mean, std) # 标准化，mean和std是数据集的均值和方差\n",
    "])\n",
    "# fashion_mnist图像分类数据集，衣服分类，60000张训练图片，10000张测试图片\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 当然也可以用 torch.utils.data.Dataset 实现人为划分"
   ],
   "outputs": [],
   "execution_count": 22
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:14:27.340800Z",
     "start_time": "2025-01-15T02:14:27.337143Z"
    }
   },
   "cell_type": "code",
   "source": [
    "img, label = train_ds[0]\n",
    "img.shape  #img这时是一个tensor，shape=(1, 28, 28)"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 23
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": [
    "#计算均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:  # 遍历每张图片,img.shape=[1,28,28]\n",
    "        mean += img.mean(dim=(1, 2))  # 计算每张图片的均值，dim=(1, 2)表示计算每张图片的每一个像素的均值,行列共同求均值\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "print(cal_mean_std(train_ds))\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T01:38:53.204831Z",
     "start_time": "2025-01-15T01:38:52.991635Z"
    }
   },
   "source": [
    "def show_imgs(n_rows, n_cols, train_ds, class_names):\n",
    "    assert n_rows * n_cols < len(train_ds)  #确保打印的图片小于总样本数\n",
    "    plt.figure(figsize = (n_cols * 1.4, n_rows * 1.6))  #宽1.4高1.6，宽，高\n",
    "    for row in range(n_rows):\n",
    "        for col in range(n_cols):\n",
    "            index = n_cols * row + col  # 计算索引，从0开始\n",
    "            plt.subplot(n_rows, n_cols, index+1)#因为从1开始\n",
    "            img_arr, label = train_ds[index]\n",
    "            img_arr = np.transpose(img_arr, (1, 2, 0))  # 通道换到最后一维\n",
    "            plt.imshow(img_arr, cmap=\"binary\",\n",
    "                       interpolation = 'nearest')#interpolation='nearest'是临近插值\n",
    "            plt.axis('off')#去除坐标系\n",
    "            plt.title(class_names[label]) # 显示类别名称\n",
    "    plt.show()\n",
    "    \n",
    "    \n",
    "\n",
    "#已知的图片类别\n",
    "# lables在这个路径https://github.com/zalandoresearch/fashion-mnist\n",
    "class_names = ['T-shirt', 'Trouser', 'Pullover', 'Dress',\n",
    "               'Coat', 'Sandal', 'Shirt', 'Sneaker',\n",
    "               'Bag', 'Ankle boot'] #0-9分别代表的类别\n",
    "#只是打印了前15个样本\n",
    "show_imgs(3, 5, train_ds, class_names)\n"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 700x480 with 15 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGMCAYAAADA5EjBAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAb4tJREFUeJztnQe41FS3hoPSe++9SRekIwqCiDQFRRFFQBRRUcGG/Cr2hogoImDFgvyi0hEFFJCuFKnSm/TeBFGQuc/KvZP7ZZ3sMOdwymTme5/nwJ7Jnkxmt+ysmi4UCoUsQgghhJAAcklaXwAhhBBCSFLhRoYQQgghgYUbGUIIIYQEFm5kCCGEEBJYuJEhhBBCSGDhRoYQQgghgYUbGUIIIYQEFm5kCCGEEBJYuJEhhBBCSGCJqo1M9+7drezZs1+wXtOmTe2/5ELOVa1atWQ7H0ketm/fbqVLl8568803L1j3+eeft+uS6IH9R0jasj1O5uBFb2SGDx9u//j69esnzxXFGa+++qo1ceJEK4hIv0fyN2fOHCuaOH36tD1po+26Uhv2X+zx6aefuvouc+bMVtGiRa2WLVtaQ4cOtU6ePJnWl0gAzsHkIf3FnuDLL7+0Spcubf3666/W5s2brfLlyyfPlcXRRqZjx45W+/btraDxxRdfuF5//vnn1syZMxO8X7ly5RS/lmeeecbq379/xJPwhRdesMvJKdkLGuy/2OXFF1+0ypQpY509e9bat2+ffcPp27ev9dZbb1mTJ0+2atSokdaXSDgHo2Mjs23bNmvhwoXW+PHjrV69etmbmueeey75ro5ENV26dHG9Xrx4sT0J9fupQfr06e0/P86fP2/9888/qXZN0Q77L3Zp1aqVVadOHef1f/7zH2vWrFlW27ZtrRtuuMFat26dlSVLFs/Pnjp1ysqWLVsqXm38wjkYBaol2bjkyZPHatOmjS1VkNd+OroPPvjAKleunJUpUyarbt261pIlSy74HStWrLAKFChg7/r+/PNPY72///7b3kSJREjOX6JECatfv372+5GybNkyq1GjRvYEl6eZkSNHJqhz4MAB6+6777YKFSpki20vv/xy67PPPvNcDB577DH7OuR6LrvsMrsNMNm4tIvUk8+HRYhiJxQvLF261BZ558+f32nzHj16eNa90Njx0u/K6wcffNAel1WrVrU/K30q40mQJ4pwu8vnSeJg/wWLZs2aWQMGDLB27NhhjR492mWXuGXLFqt169ZWjhw5rDvuuMO5ab399tt228taJ2uePLAePXo00ePgq6++smrXrm2fP2fOnFb16tWtd955JxV/fWzCOZgMEhn5cTfddJOVMWNGq3PnztaIESPsxpFG0owZM8bWz8pEkB/9xhtv2J/dunWrlSFDBs/zy7mkk+TJYtKkScYnCJlw8pQxf/58695777XFcKtXr7aGDBlibdy4MSIbFJmcMpFvvfVW+7d8/fXX1v3332//tvDA+Ouvv+wNlajQpHNl0HzzzTf2YnDs2DGrT58+dj3ZrMj1zJ4929701KxZ05o+fbr1xBNPWLt377avSxDx4T333GPVq1fPvm5BBlo8IBvC6667zp4QIs7MnTu3vekV6V5yjJ0w8hQqfSn9JZNdNp4yTqVvO3ToYJ9HoKg9cbD/gsmdd95pPfXUU9aMGTOsnj172u+dO3fOXmcbN25sP2xlzZrVfl/6S2xu7rrrLuvhhx+2JfDDhg2zfvvtN2vBggV230UyDkTCIGtq8+bNrYEDB9rviURIzhFeM0ni4RwEQklk6dKlIloIzZw50359/vz5UPHixUN9+vRx1du2bZtdL1++fKEjR44470+aNMl+f8qUKc573bp1C2XLls0uz58/P5QzZ85QmzZtQmfOnHGds0mTJvZfmC+++CJ0ySWXhObNm+eqN3LkSPs7FixY4Ptb5FxSb/Dgwc57f//9d6hmzZqhggULhv755x/7vbffftuuN3r0aKeeHGvYsGEoe/bsoRMnTtjvTZw40a738ssvu76nY8eOoXTp0oU2b97svCe/V353LNC7d2/7d0fChAkT7LpLliwx1knM2HnuuecSfLe8lnGxdu1a1/sHDx60j8lnyP/D/gs+o0aNumC/5MqVK1SrVi27LGuP1O/fv7+rjqyl8v6XX37pev+HH35wvR/JOJB7gqzl586du8hfF/twDiaNSy5GGiOixmuuucZ+Lbu8Tp062SLEf//9N0F9OSZqqDBXXXWV/b/sCDUiyZAnBNnBy+5SxFl+iFREpDCVKlWyDh065PyJKDV8vgshukHZrYYRSYy8ll2vqJyEadOmWYULF7afLsLIblaeVkTt9fPPPzv1Lr30Uvt9RFRNMja+//57K96Rpwdh6tSptkGiH4kZO5omTZpYVapU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YOFGhhBCCCGBhRsZQgghhASWmN7IbN++3UqXLp315ptvXrDu888/b9clF0f37t2t7NmzX7Be06ZN7b/kQs5VrVq1ZDsfSV0+/fRTe/7JnE3KmCtdunSKXBeJDPZffNwno5U03chI40XyN2fOHCuaOH36tL3xibbrSirDhw+327l+/fppfSmB5NVXX7UmTpxoBY3Vq1dbHTt2tEqVKmVlzpzZKlasmNWiRQvr3XffTetLIxHA/gsO7KuUJb2VhnzxxReu159//rk1c+bMBO9Xrlw5xa/lmWeesfr37x/xRuaFF16wy8kpVUgrvvzyS/uJ6Ndff7U2b95slS9fPq0vKXAbGVmk2rdvbwWFhQsXWtdcc41VsmRJq2fPnlbhwoWtnTt3WosXL7beeecd66GHHkrrSyQ+sP+CA/sqxjcyXbp0cb2WjpWNjH4/NUifPr3958f58+etf/75x4oltm3bZk+08ePHW7169bI3Nc8991xaXxZJYV555RUrV65c1pIlS6zcuXO7jh04cCDNrotEBvsvOLCvLPvhP2vWrCl2/kDbyCxdutRq2bKllT9/fitLlixWmTJlrB49enjW/eCDD6xy5cpZmTJlsurWrWsPqgvZyMjrBx980L65V61a1f7syJEjrQIFCtjHRSoTVn/J54OI/LY8efJYbdq0saUK8tpPh3qhdvRixYoVdpuJ9OrPP/801vv777/tTZRIhOT8JUqUsPr162e/HynLli2zGjVq5IwH6S+NLB533323VahQIVvMe/nll1ufffZZgnqnTp2yHnvsMfs65Houu+wyuw1CoZBTR9pF6snnw2NBdP7RzpYtW+wxrRdWoWDBgk551KhRVrNmzez3pA2qVKlijRgxIsFnRKLXtm1ba/78+Va9evXsdi1btqwtZdWsXbvWPqf0UfHixa2XX37ZfkjQTJo0yR6XRYsWtb9bxt1LL71k/fvvv1a8w/6Lvb4K329ETS32ftJm8rkffvghwed2795t3+tkDcv0f/U++eQTVx156H722Wet2rVr2xupbNmyWVdddZU1e/bsC16zrHH33nuvlTFjRvshN8zo0aPt80nf582b17rtttts6ZKXvaKsxVdffbW9gXnqqaesmJXIXAxyM7ruuuvsG6SohGSQyA0XGz3MmDFjrJMnT9oSBxksb7zxhnXTTTdZW7dutTJkyOD7PbNm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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 8
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T01:46:38.064599Z",
     "start_time": "2025-01-15T01:46:38.061257Z"
    }
   },
   "source": [
    "# 从数据集到dataloader\n",
    "train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True) #batch_size分批，shuffle洗牌\n",
    "val_loader = torch.utils.data.DataLoader(test_ds, batch_size=32, shuffle=False)"
   ],
   "outputs": [],
   "execution_count": 9
  },
  {
   "cell_type": "markdown",
   "source": [
    "在PyTorch中，`DataLoader`是一个迭代器，它封装了数据的加载和预处理过程，使得在训练机器学习模型时可以方便地批量加载数据。`DataLoader`主要负责以下几个方面：\n",
    "\n",
    "1. **批量加载数据**：`DataLoader`可以将数据集（Dataset）切分为更小的批次（batch），每次迭代提供一小批量数据，而不是单个数据点。这有助于模型学习数据中的统计依赖性，并且可以更高效地利用GPU等硬件的并行计算能力。\n",
    "\n",
    "2. **数据打乱**：默认情况下，`DataLoader`会在每个epoch（训练周期）开始时打乱数据的顺序。这有助于模型训练时避免陷入局部最优解，并且可以提高模型的泛化能力。\n",
    "\n",
    "3. **多线程数据加载**：`DataLoader`支持多线程（通过参数`num_workers`）来并行地加载数据，这可以显著减少训练过程中的等待时间，尤其是在处理大规模数据集时。\n",
    "\n",
    "4. **数据预处理**：`DataLoader`可以与`transforms`结合使用，对加载的数据进行预处理，如归一化、标准化、数据增强等操作。\n",
    "\n",
    "5. **内存管理**：`DataLoader`负责管理数据的内存使用，确保在训练过程中不会耗尽内存资源。\n",
    "\n",
    "6. **易用性**：`DataLoader`提供了一个简单的接口，可以很容易地集成到训练循环中。\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:27:52.029581Z",
     "start_time": "2025-01-15T02:27:52.017310Z"
    }
   },
   "cell_type": "code",
   "source": [
    "for datas, labels in train_loader:\n",
    "    print(datas.shape)\n",
    "    print(labels.shape)\n",
    "    break\n",
    "#查看val_loader\n",
    "for datas, labels in val_loader:\n",
    "    print(datas.shape)\n",
    "    print(labels.shape)\n",
    "    break"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([32, 1, 28, 28])\n",
      "torch.Size([32])\n",
      "torch.Size([32, 1, 28, 28])\n",
      "torch.Size([32])\n"
     ]
    }
   ],
   "execution_count": 24
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:41:42.214317Z",
     "start_time": "2025-01-15T02:41:42.209523Z"
    }
   },
   "source": [
    "class NeuralNetwork(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__() # 继承父类的初始化方法，子类有父类的属性\n",
    "        self.flatten = nn.Flatten()  # 展平层\n",
    "        self.linear_relu_stack = nn.Sequential(\n",
    "            nn.Linear(784, 300),  # in_features=784, out_features=300, 784是输入特征数，300是输出特征数\n",
    "            nn.ReLU(), # 激活函数\n",
    "            nn.Linear(300, 100),#隐藏层神经元数100\n",
    "            nn.ReLU(), # 激活函数\n",
    "            nn.Linear(100, 10),#输出层神经元数10 \n",
    "        )\n",
    "\n",
    "    def forward(self, x): # 前向计算，前向传播\n",
    "        # x.shape [batch size, 1, 28, 28],1是通道数\n",
    "        x = self.flatten(x)  \n",
    "        # print(f'x.shape--{x.shape}')\n",
    "        # 展平后 x.shape [batch size, 784]\n",
    "        logits = self.linear_relu_stack(x)\n",
    "        # logits.shape [batch size, 10]\n",
    "        return logits #没有经过softmax,称为logits\n",
    "    \n",
    "model = NeuralNetwork()"
   ],
   "outputs": [],
   "execution_count": 36
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:33:30.010091Z",
     "start_time": "2025-01-15T02:33:30.007355Z"
    }
   },
   "source": [
    "# 看看网络结构\n",
    "model"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "NeuralNetwork(\n",
       "  (flatten): Flatten(start_dim=1, end_dim=-1)\n",
       "  (linear_relu_stack): Sequential(\n",
       "    (0): Linear(in_features=784, out_features=300, bias=True)\n",
       "    (1): ReLU()\n",
       "    (2): Linear(in_features=300, out_features=100, bias=True)\n",
       "    (3): ReLU()\n",
       "    (4): Linear(in_features=100, out_features=10, bias=True)\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 27
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:41:29.428586Z",
     "start_time": "2025-01-15T02:41:29.424878Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#为了查看模型运算的tensor尺寸\n",
    "x = torch.randn(32, 1, 28, 28)\n",
    "print(x.shape)\n",
    "logits = model(x)\n",
    "print(logits.shape)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([32, 1, 28, 28])\n",
      "x.shapetorch.Size([32, 784])\n",
      "torch.Size([32, 10])\n"
     ]
    }
   ],
   "execution_count": 35
  },
  {
   "cell_type": "code",
   "source": [
    "784*300+300+300*100+100+100*10+10"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T02:34:28.868806Z",
     "start_time": "2025-01-15T02:34:28.865311Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "266610"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 28
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:38:23.349319Z",
     "start_time": "2025-01-15T02:38:23.346015Z"
    }
   },
   "source": [
    "for name, param in model.named_parameters(): # 打印模型参数\n",
    "      print(name, param.shape)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "linear_relu_stack.0.weight torch.Size([300, 784])\n",
      "linear_relu_stack.0.bias torch.Size([300])\n",
      "linear_relu_stack.2.weight torch.Size([100, 300])\n",
      "linear_relu_stack.2.bias torch.Size([100])\n",
      "linear_relu_stack.4.weight torch.Size([10, 100])\n",
      "linear_relu_stack.4.bias torch.Size([10])\n"
     ]
    }
   ],
   "execution_count": 30
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:47:39.617675Z",
     "start_time": "2025-01-15T02:47:39.607784Z"
    }
   },
   "source": [
    "# 看看模型参数\n",
    "list(model.parameters())  # 这种方法拿到模型的所有可学习参数,requires_grad=True\n"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Parameter containing:\n",
       " tensor([[ 0.0193,  0.0129,  0.0254,  ..., -0.0257, -0.0175, -0.0086],\n",
       "         [-0.0196,  0.0020, -0.0148,  ..., -0.0153, -0.0165, -0.0058],\n",
       "         [ 0.0264,  0.0100, -0.0072,  ..., -0.0321,  0.0221,  0.0179],\n",
       "         ...,\n",
       "         [-0.0207,  0.0125,  0.0267,  ...,  0.0014, -0.0336,  0.0141],\n",
       "         [-0.0044,  0.0256,  0.0048,  ...,  0.0356, -0.0295,  0.0041],\n",
       "         [ 0.0020,  0.0264,  0.0023,  ..., -0.0357, -0.0184,  0.0222]],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([ 0.0355,  0.0116, -0.0354, -0.0079,  0.0184, -0.0039, -0.0007,  0.0348,\n",
       "         -0.0266, -0.0277, -0.0081, -0.0155,  0.0282, -0.0193,  0.0271,  0.0113,\n",
       "          0.0276, -0.0267, -0.0168,  0.0080, -0.0199,  0.0016, -0.0271, -0.0134,\n",
       "         -0.0220,  0.0057, -0.0146, -0.0266,  0.0290, -0.0261,  0.0068,  0.0180,\n",
       "          0.0068, -0.0158,  0.0068, -0.0133, -0.0212, -0.0158, -0.0254,  0.0119,\n",
       "          0.0123,  0.0197,  0.0295, -0.0137,  0.0306,  0.0052,  0.0290,  0.0085,\n",
       "         -0.0331,  0.0143, -0.0238,  0.0127, -0.0249,  0.0324,  0.0119,  0.0183,\n",
       "         -0.0294, -0.0074, -0.0263,  0.0199, -0.0117,  0.0136, -0.0076,  0.0146,\n",
       "          0.0066, -0.0117, -0.0357,  0.0326, -0.0187, -0.0100, -0.0160, -0.0088,\n",
       "          0.0319, -0.0027,  0.0009,  0.0128,  0.0300,  0.0033,  0.0071,  0.0045,\n",
       "          0.0084, -0.0041,  0.0345,  0.0106, -0.0031, -0.0297, -0.0285, -0.0260,\n",
       "          0.0178,  0.0266, -0.0183,  0.0232,  0.0098, -0.0202, -0.0138,  0.0220,\n",
       "         -0.0085,  0.0266, -0.0249,  0.0151,  0.0216, -0.0180, -0.0199, -0.0151,\n",
       "          0.0278,  0.0165, -0.0058,  0.0286,  0.0145,  0.0319, -0.0351,  0.0207,\n",
       "         -0.0314,  0.0201, -0.0202,  0.0191,  0.0088, -0.0142,  0.0227,  0.0174,\n",
       "          0.0097, -0.0105, -0.0227, -0.0315, -0.0146,  0.0151,  0.0325,  0.0216,\n",
       "         -0.0059, -0.0326, -0.0206,  0.0089,  0.0109, -0.0105, -0.0171, -0.0063,\n",
       "          0.0233, -0.0263,  0.0145,  0.0078,  0.0117, -0.0087, -0.0002, -0.0123,\n",
       "          0.0311, -0.0225, -0.0229,  0.0096, -0.0158, -0.0297,  0.0302, -0.0082,\n",
       "         -0.0189,  0.0341, -0.0280, -0.0086, -0.0322,  0.0274,  0.0197,  0.0310,\n",
       "         -0.0039, -0.0102, -0.0158,  0.0285,  0.0147, -0.0086,  0.0042,  0.0346,\n",
       "          0.0145,  0.0161,  0.0115, -0.0042,  0.0137, -0.0123,  0.0084, -0.0324,\n",
       "         -0.0270,  0.0035,  0.0309, -0.0238,  0.0166, -0.0337,  0.0015,  0.0042,\n",
       "         -0.0009,  0.0161,  0.0077, -0.0094,  0.0079,  0.0102, -0.0157,  0.0069,\n",
       "          0.0089, -0.0133,  0.0004,  0.0077,  0.0293,  0.0348,  0.0197,  0.0169,\n",
       "         -0.0015,  0.0239, -0.0287,  0.0130,  0.0198, -0.0116,  0.0180,  0.0189,\n",
       "         -0.0018,  0.0035, -0.0236,  0.0298,  0.0205, -0.0057,  0.0080, -0.0139,\n",
       "         -0.0053, -0.0157, -0.0210,  0.0307, -0.0039, -0.0151,  0.0010, -0.0081,\n",
       "          0.0128, -0.0266,  0.0154, -0.0006,  0.0072,  0.0246,  0.0341, -0.0004,\n",
       "          0.0116,  0.0193,  0.0279,  0.0328, -0.0179, -0.0152,  0.0197, -0.0244,\n",
       "          0.0246, -0.0264,  0.0259,  0.0157, -0.0048, -0.0155,  0.0133, -0.0335,\n",
       "          0.0206,  0.0115,  0.0162,  0.0124, -0.0327, -0.0243,  0.0050,  0.0267,\n",
       "         -0.0021, -0.0062,  0.0221,  0.0267, -0.0280,  0.0232, -0.0079,  0.0089,\n",
       "          0.0146, -0.0148,  0.0015,  0.0257,  0.0205,  0.0162,  0.0019,  0.0103,\n",
       "         -0.0248,  0.0344, -0.0062,  0.0094, -0.0261, -0.0128,  0.0335, -0.0042,\n",
       "         -0.0136, -0.0326, -0.0039, -0.0161, -0.0221, -0.0111,  0.0234,  0.0357,\n",
       "          0.0005, -0.0183, -0.0234,  0.0322,  0.0055, -0.0148,  0.0191,  0.0265,\n",
       "          0.0214, -0.0211, -0.0314, -0.0136], requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([[ 0.0247, -0.0074, -0.0172,  ...,  0.0120,  0.0069, -0.0211],\n",
       "         [ 0.0324, -0.0217, -0.0183,  ..., -0.0444, -0.0305, -0.0155],\n",
       "         [-0.0172, -0.0306, -0.0129,  ..., -0.0265,  0.0148,  0.0212],\n",
       "         ...,\n",
       "         [ 0.0541,  0.0279, -0.0005,  ..., -0.0354, -0.0103,  0.0166],\n",
       "         [ 0.0316, -0.0281,  0.0363,  ..., -0.0223, -0.0539,  0.0456],\n",
       "         [ 0.0482, -0.0474,  0.0301,  ..., -0.0454, -0.0088,  0.0179]],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([-0.0549,  0.0067, -0.0281, -0.0304, -0.0371, -0.0007, -0.0034, -0.0061,\n",
       "         -0.0564,  0.0514, -0.0263,  0.0522, -0.0084, -0.0018, -0.0548,  0.0272,\n",
       "          0.0424, -0.0253, -0.0508, -0.0132, -0.0102,  0.0322,  0.0162,  0.0352,\n",
       "         -0.0525,  0.0209, -0.0031,  0.0409,  0.0040,  0.0390, -0.0143,  0.0093,\n",
       "         -0.0206, -0.0345, -0.0315,  0.0208,  0.0551,  0.0500, -0.0232, -0.0569,\n",
       "          0.0516,  0.0166,  0.0548, -0.0078,  0.0005,  0.0376, -0.0212, -0.0116,\n",
       "          0.0424,  0.0137,  0.0022,  0.0541,  0.0476,  0.0030,  0.0182, -0.0405,\n",
       "          0.0260, -0.0533, -0.0438,  0.0247, -0.0440, -0.0030,  0.0240,  0.0400,\n",
       "          0.0081, -0.0209,  0.0381,  0.0421,  0.0088,  0.0404,  0.0523,  0.0242,\n",
       "         -0.0383,  0.0333, -0.0020,  0.0416,  0.0020,  0.0491,  0.0569, -0.0096,\n",
       "         -0.0269,  0.0318, -0.0287,  0.0485, -0.0086, -0.0453,  0.0102,  0.0335,\n",
       "          0.0488, -0.0516, -0.0347,  0.0226,  0.0490, -0.0038,  0.0099,  0.0045,\n",
       "         -0.0420, -0.0044,  0.0205,  0.0248], requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([[-3.5601e-02, -9.7942e-02, -8.8577e-02,  4.6133e-02,  3.3578e-03,\n",
       "          -5.9538e-02,  8.9883e-02,  4.2652e-02, -7.2786e-02, -4.4290e-02,\n",
       "          -8.5018e-02,  7.8373e-02, -5.2688e-02,  7.1229e-03,  9.8994e-02,\n",
       "          -2.4532e-02,  3.9207e-02,  6.6676e-02, -7.2313e-02,  6.8713e-02,\n",
       "           5.2375e-02, -9.5469e-02, -3.9689e-02, -7.9994e-02,  5.4932e-02,\n",
       "          -4.1948e-02, -6.4123e-02,  4.8918e-02, -5.1706e-02, -5.3377e-03,\n",
       "           9.5127e-02,  4.4926e-02,  9.5097e-02,  5.4957e-02,  8.8354e-02,\n",
       "           1.8326e-02,  3.9696e-02, -1.7166e-02,  1.4899e-02,  9.1671e-02,\n",
       "          -2.3972e-03,  8.8529e-02, -2.9868e-02,  1.0284e-02, -5.7374e-02,\n",
       "           3.2708e-02, -8.0831e-02,  9.0553e-02,  4.9517e-03, -7.8128e-02,\n",
       "           4.8253e-02, -9.2206e-02,  8.1480e-02, -8.1546e-02, -5.3104e-02,\n",
       "           1.3686e-02,  2.8876e-02, -6.1871e-02, -1.2388e-02,  8.4163e-02,\n",
       "          -4.1674e-02,  6.7441e-02, -2.3494e-02,  1.7277e-02, -4.4024e-03,\n",
       "           1.9306e-02, -5.4167e-02,  6.2217e-03,  4.5384e-02,  3.9507e-02,\n",
       "           6.8822e-02, -4.4401e-02, -6.7542e-02,  8.8495e-02,  4.0803e-02,\n",
       "           3.5141e-02,  2.3298e-02,  1.2978e-02, -8.9307e-02,  1.7340e-02,\n",
       "          -9.3287e-02, -8.7212e-02, -7.8308e-02, -7.0968e-02, -4.4588e-02,\n",
       "           7.6964e-02,  5.6563e-02, -1.8374e-02, -2.6539e-02, -6.3119e-02,\n",
       "           2.7789e-02,  7.4602e-02,  8.8759e-03, -6.3711e-02, -4.5685e-02,\n",
       "           2.3983e-02,  1.2134e-02, -7.5184e-02,  4.4194e-02, -5.6144e-02],\n",
       "         [-9.8274e-02,  8.1675e-02,  6.5160e-02, -8.3878e-02, -3.0522e-02,\n",
       "          -6.0764e-02,  7.5422e-02, -9.3385e-02,  7.8451e-02,  8.3842e-02,\n",
       "          -4.3887e-02, -3.7606e-02,  6.0842e-02, -7.6966e-02, -3.1290e-02,\n",
       "          -8.8149e-02, -5.0624e-03,  5.8349e-02,  3.2895e-02,  4.1435e-02,\n",
       "          -7.2758e-02, -1.5722e-02, -2.8167e-02, -5.1797e-02,  8.7033e-02,\n",
       "           2.4171e-02,  4.0116e-03,  3.0599e-02, -3.4999e-02,  7.8467e-02,\n",
       "          -4.0908e-02,  2.6092e-03,  4.3027e-03,  2.0698e-03, -4.9047e-02,\n",
       "          -5.2967e-02, -4.3314e-02,  5.6072e-02, -9.9253e-02,  7.3400e-02,\n",
       "           2.6134e-02,  9.8886e-02, -8.0145e-02,  3.0487e-02, -2.4529e-02,\n",
       "           3.8392e-02, -8.3920e-02,  6.0344e-02, -4.6361e-02,  3.2300e-02,\n",
       "           9.3868e-02,  6.7847e-02,  5.2724e-02, -2.0351e-02, -3.8824e-02,\n",
       "           8.8460e-02, -2.3352e-02, -5.0685e-02, -4.8574e-02, -8.8746e-02,\n",
       "          -9.0050e-02,  8.5539e-02, -3.8432e-02, -1.3920e-02, -1.3610e-02,\n",
       "          -4.6103e-02,  2.2419e-02,  8.6283e-02, -8.7566e-02,  7.4887e-02,\n",
       "           1.7377e-02,  1.0543e-02,  9.5762e-02,  9.2902e-02, -8.3409e-02,\n",
       "           4.6540e-02,  3.8619e-02, -5.4852e-02,  4.5651e-02, -4.8946e-02,\n",
       "          -6.7331e-02,  2.0054e-02, -8.8737e-03,  1.9723e-02, -5.9118e-03,\n",
       "           8.0712e-02, -5.3340e-02,  5.5798e-02,  4.3567e-02,  4.9788e-02,\n",
       "           1.6180e-02,  9.4240e-02,  6.1814e-03,  8.2957e-02, -3.5374e-02,\n",
       "           4.2070e-02, -9.6864e-02, -4.8976e-02,  6.7795e-02,  3.2200e-03],\n",
       "         [-2.7292e-03, -9.2022e-02, -7.3330e-02, -9.6081e-02,  4.1453e-02,\n",
       "           4.5537e-02, -6.1371e-02,  6.7853e-02,  1.5310e-02,  6.5403e-02,\n",
       "           5.1755e-02, -5.2207e-02, -8.8505e-02,  3.5228e-03,  1.1635e-02,\n",
       "           5.8740e-03,  4.7143e-02,  3.1183e-04,  1.8770e-02,  1.0510e-02,\n",
       "          -2.3647e-02,  9.4697e-02,  9.9580e-03,  8.3015e-02, -4.3743e-02,\n",
       "           1.7195e-02, -5.1303e-02, -6.1418e-02,  2.9727e-02,  8.3634e-02,\n",
       "           9.0352e-02, -9.0317e-02, -9.0726e-03,  4.8960e-02, -1.7573e-02,\n",
       "          -1.7171e-02, -6.7439e-02, -8.1699e-02, -6.1322e-02,  3.4608e-02,\n",
       "           8.6266e-02, -2.4879e-02, -1.6067e-02,  2.8891e-02,  5.0291e-02,\n",
       "           1.2828e-02,  3.8646e-03, -9.9567e-02, -7.0176e-02,  9.8847e-02,\n",
       "           8.7816e-02, -6.9187e-02, -1.9238e-02,  9.5543e-04,  1.8534e-02,\n",
       "          -2.2314e-03, -9.8567e-02,  5.6000e-02, -6.5039e-02, -8.6415e-02,\n",
       "           8.3800e-02, -2.7922e-02,  5.6865e-02,  5.6090e-03, -8.5642e-02,\n",
       "           9.8887e-02, -3.4404e-02,  5.6317e-03, -8.0823e-02, -9.8466e-03,\n",
       "          -4.3589e-02, -5.2469e-02, -5.9490e-03,  4.2756e-02, -9.0112e-02,\n",
       "          -4.2695e-02,  6.8533e-02, -3.0138e-02, -4.7132e-02,  1.4999e-02,\n",
       "           1.4187e-02,  9.3698e-02,  2.2677e-02,  6.0830e-02,  8.5666e-02,\n",
       "          -5.1759e-02, -4.4511e-02, -8.1692e-02,  6.7885e-02,  4.5821e-02,\n",
       "           6.6097e-02, -3.4991e-02,  8.8831e-02, -5.2271e-02, -8.4212e-02,\n",
       "           1.3594e-02,  8.2421e-02, -4.8503e-02,  4.7768e-02,  8.1849e-02],\n",
       "         [ 5.0437e-02, -1.8996e-02,  1.2338e-03, -5.4597e-03, -6.1513e-02,\n",
       "          -1.1248e-03, -1.7887e-02,  1.3916e-02,  7.2851e-02, -2.5220e-02,\n",
       "           1.9290e-02, -3.0227e-02, -4.6373e-02, -1.9455e-02,  2.9227e-02,\n",
       "          -4.4148e-02,  7.1989e-02,  8.6114e-02,  7.1265e-02, -8.7936e-02,\n",
       "           3.5527e-02,  6.1438e-02, -8.0527e-02, -3.2068e-03,  9.0487e-02,\n",
       "          -3.9917e-02, -6.9579e-02, -5.0209e-04,  5.5645e-02,  4.2119e-02,\n",
       "           6.6046e-02, -3.1766e-02, -4.0555e-03, -5.9547e-02,  4.9122e-02,\n",
       "          -5.2137e-02,  1.2769e-02,  5.4010e-02,  6.3224e-02,  5.0570e-04,\n",
       "          -5.9504e-02,  8.3342e-02,  6.5837e-02, -3.0805e-02,  7.3220e-02,\n",
       "           8.0144e-02,  9.1250e-02,  7.7802e-02,  5.1345e-03,  5.8143e-02,\n",
       "           8.7456e-04, -8.8680e-02, -7.8230e-02,  6.6349e-02, -5.1923e-02,\n",
       "          -3.0909e-02,  1.5088e-02, -3.3623e-02, -8.1530e-02, -6.6689e-03,\n",
       "          -8.7721e-02,  7.7998e-02,  5.4764e-02,  7.9612e-02,  9.4378e-02,\n",
       "           9.0028e-02,  7.7461e-02,  1.4474e-02,  9.4429e-02, -3.5624e-02,\n",
       "           7.9655e-02,  9.1062e-02,  5.0732e-02, -7.6293e-02,  4.0589e-02,\n",
       "           9.6033e-02,  2.4112e-02, -1.7267e-02,  7.1529e-02,  5.8671e-02,\n",
       "           1.0598e-02, -8.1457e-02,  6.2489e-02,  9.3421e-02,  6.5994e-02,\n",
       "          -4.5167e-02, -2.0387e-02,  2.1087e-02,  9.1141e-02, -3.8978e-02,\n",
       "          -2.6662e-02, -8.6336e-02,  7.9130e-02, -3.2844e-03, -2.4792e-02,\n",
       "           5.9617e-02, -1.8155e-02,  6.7560e-02, -9.6414e-02, -6.3195e-02],\n",
       "         [-7.6716e-02,  5.0012e-02, -9.3130e-02, -1.3011e-02,  8.5772e-02,\n",
       "           9.3530e-02,  6.2733e-02,  1.2917e-02,  1.8966e-02, -4.7746e-02,\n",
       "           4.0909e-02,  4.0541e-02,  1.1801e-03, -6.4642e-02, -8.9587e-02,\n",
       "           3.3321e-03, -2.3482e-03, -5.7087e-02, -8.3191e-02,  1.3958e-02,\n",
       "          -8.5284e-02, -2.0577e-02, -1.6377e-02, -1.8272e-02, -4.4092e-02,\n",
       "           3.6336e-02, -9.1701e-02,  3.2003e-02, -7.2300e-02,  9.2544e-02,\n",
       "          -5.3201e-02,  5.2336e-02, -3.3710e-02, -8.2335e-02, -6.4696e-02,\n",
       "          -3.9820e-02, -8.2748e-03,  7.4576e-03, -1.6969e-02, -1.2378e-02,\n",
       "           5.5833e-03,  1.3232e-04,  2.7453e-02, -5.9838e-02,  1.8426e-02,\n",
       "          -4.6022e-02, -6.4367e-04,  9.1400e-02,  5.7939e-03,  5.2112e-02,\n",
       "           2.9353e-02,  3.2336e-02,  5.4383e-02,  5.5465e-02,  3.6522e-02,\n",
       "           4.1094e-02, -9.4556e-02, -2.3188e-02, -5.7130e-02, -2.6848e-02,\n",
       "          -4.7451e-02,  2.7504e-02, -9.0964e-02, -3.4647e-02,  9.6648e-02,\n",
       "          -2.9473e-02,  2.8667e-02,  8.0833e-02, -7.3630e-02, -6.5799e-02,\n",
       "           2.0050e-02,  3.3241e-02,  1.3586e-03,  5.3845e-02,  2.6745e-02,\n",
       "           4.4362e-02, -7.6688e-02, -9.0940e-02,  1.2185e-02, -2.5316e-03,\n",
       "          -1.3300e-02, -2.5591e-02, -9.9013e-02, -3.3321e-02,  6.5190e-02,\n",
       "          -4.8627e-02,  3.3726e-03, -6.9335e-02, -9.1007e-02, -1.3590e-02,\n",
       "           3.4004e-02,  6.4099e-02, -7.1526e-02, -4.8801e-02,  4.8006e-02,\n",
       "          -2.9146e-02,  3.6318e-02, -3.2495e-02,  7.0003e-02,  9.0116e-02],\n",
       "         [ 5.2724e-02,  3.3650e-02,  1.5227e-02,  5.9439e-02, -3.1375e-02,\n",
       "          -1.3921e-02, -5.6623e-02, -1.4438e-02,  3.7056e-02,  5.3632e-02,\n",
       "           4.6734e-02,  3.8892e-02, -4.8980e-03, -8.9461e-02, -6.4321e-02,\n",
       "          -5.0307e-02, -2.1354e-02,  3.0360e-02, -7.5975e-02,  2.2117e-02,\n",
       "           9.0628e-02,  7.2030e-02, -3.6488e-02,  6.8247e-02, -3.0882e-02,\n",
       "          -7.4132e-02,  4.3945e-02, -3.7811e-02, -6.7319e-03, -4.2572e-02,\n",
       "          -2.4123e-02,  9.8532e-02,  5.4432e-02,  9.0232e-02, -7.7567e-03,\n",
       "           1.4849e-02, -5.8721e-03,  4.6753e-02, -7.7158e-02, -1.6075e-02,\n",
       "          -1.1672e-02,  2.8535e-02, -2.3614e-02, -4.5656e-02,  4.9980e-02,\n",
       "          -3.0185e-02, -2.3355e-02, -4.2122e-02, -6.6083e-02, -2.3434e-02,\n",
       "           3.1393e-02, -1.8822e-02,  8.5668e-02, -9.7642e-02, -2.7145e-02,\n",
       "          -6.1501e-02, -9.9856e-02,  1.4698e-02, -6.4478e-02,  6.8782e-02,\n",
       "           1.6452e-02,  9.7138e-02,  9.7042e-02, -1.3597e-02, -4.1204e-02,\n",
       "          -5.4675e-02,  3.0663e-02,  4.6285e-02, -6.8216e-02, -8.1160e-02,\n",
       "          -9.7382e-02, -6.8406e-02, -2.1864e-02, -9.3965e-02, -5.4067e-02,\n",
       "           5.3537e-04,  8.4304e-02,  4.1267e-03,  2.6284e-03, -2.0604e-02,\n",
       "          -7.6307e-03, -3.1849e-02,  5.7251e-02, -9.6512e-02,  7.5927e-02,\n",
       "          -2.3879e-02,  7.2066e-03,  3.3317e-02, -5.2414e-02,  9.2820e-02,\n",
       "           5.8188e-02, -8.7421e-02, -4.7356e-02, -7.0014e-04, -1.1755e-02,\n",
       "           4.6205e-02, -7.7137e-02, -1.3514e-02, -2.4242e-02, -1.7911e-02],\n",
       "         [ 1.2473e-02,  4.8242e-02, -1.6912e-02, -7.4142e-02, -8.2475e-02,\n",
       "           1.2610e-02, -1.1435e-02,  8.2715e-02, -1.0556e-02,  3.7860e-03,\n",
       "           5.3005e-02, -4.6915e-02, -9.6198e-02,  8.3650e-02, -6.2799e-02,\n",
       "           2.6640e-02,  1.7723e-03, -9.5108e-02, -2.4597e-02,  1.2462e-02,\n",
       "          -3.4732e-02,  6.7540e-02, -4.8088e-02, -5.2946e-02,  1.9943e-02,\n",
       "          -8.6499e-03, -7.0518e-02,  2.3185e-02,  6.1935e-02,  6.8027e-02,\n",
       "           5.4856e-02,  9.9004e-02,  1.3595e-02, -6.7790e-02, -2.4762e-03,\n",
       "           9.2696e-02, -5.9300e-02,  3.3065e-04, -9.8599e-02,  9.6327e-02,\n",
       "          -1.9767e-02, -4.9256e-02, -2.7733e-02, -9.8894e-02,  1.0437e-02,\n",
       "          -7.5219e-02,  5.9923e-02, -8.2564e-02,  3.9559e-02, -1.2431e-02,\n",
       "          -8.6394e-02, -2.2048e-02, -1.7044e-02,  5.1152e-02,  9.3816e-02,\n",
       "          -5.1866e-02, -4.7448e-02, -9.4013e-02,  4.9015e-02, -9.6499e-02,\n",
       "          -4.1475e-03,  7.7643e-02,  9.4576e-02,  9.3993e-02,  2.0931e-02,\n",
       "           9.2164e-06, -4.5430e-02, -4.8807e-02, -8.7959e-02, -3.8213e-02,\n",
       "           5.2134e-03,  4.7976e-02, -7.9541e-02,  6.1658e-02, -7.9375e-02,\n",
       "           9.5074e-02, -4.3509e-02,  3.9506e-02,  1.8377e-02, -1.5930e-02,\n",
       "          -8.4778e-02,  2.1484e-03, -8.1433e-02, -7.1122e-02, -1.8857e-02,\n",
       "           7.7652e-02,  2.8550e-02, -1.9790e-02,  9.4921e-02, -2.6958e-02,\n",
       "          -6.6783e-02, -3.0767e-02,  2.3986e-02, -5.6730e-02, -4.7162e-02,\n",
       "           7.4180e-02,  5.1950e-03,  9.4514e-02,  9.3489e-02, -5.7837e-02],\n",
       "         [-8.6574e-02, -1.9518e-02, -1.9963e-02,  7.1117e-02, -8.1258e-02,\n",
       "          -9.6614e-02, -3.9235e-02,  3.6748e-02, -5.6711e-03,  6.9479e-02,\n",
       "           9.0873e-04, -5.9999e-02, -2.9546e-02,  8.8007e-02, -2.5237e-02,\n",
       "           6.1512e-02,  3.8649e-02, -4.2422e-02, -9.3176e-02,  6.1351e-02,\n",
       "           6.7181e-02, -5.7764e-02, -7.4153e-02,  8.5875e-02,  1.7113e-02,\n",
       "          -6.8341e-02,  9.3672e-02, -6.8019e-02,  5.3969e-02,  1.3708e-02,\n",
       "           5.5512e-02,  8.8355e-02, -9.3288e-02,  2.6569e-02, -6.3146e-02,\n",
       "          -5.9552e-02,  3.9571e-03,  4.9719e-02, -3.7555e-02, -2.0574e-02,\n",
       "           9.1595e-02,  5.9522e-02,  1.1716e-02,  6.0011e-02, -4.7558e-03,\n",
       "           5.9612e-03,  4.2376e-02,  6.3682e-02,  9.1773e-02,  8.1829e-02,\n",
       "          -7.4296e-02,  2.5552e-02,  5.3048e-02, -5.1959e-02, -5.8132e-02,\n",
       "          -9.4031e-02,  3.7542e-02,  5.6474e-02, -7.7625e-02,  9.1964e-02,\n",
       "           3.7964e-02, -9.2419e-02,  3.1097e-02,  7.0547e-02, -8.6851e-02,\n",
       "          -3.9449e-02, -1.4707e-02, -4.7596e-02,  9.6723e-02,  2.7980e-02,\n",
       "           6.9301e-02,  2.6861e-02,  5.0863e-02,  8.3203e-02, -1.2703e-02,\n",
       "          -6.5912e-02,  2.5853e-02, -7.2680e-03, -3.4418e-02,  6.9764e-02,\n",
       "          -3.1934e-02, -2.1547e-02, -2.6072e-02, -9.2962e-03, -7.0831e-02,\n",
       "          -5.5957e-02,  8.4440e-03,  4.6133e-02,  5.9199e-02,  9.7271e-02,\n",
       "           8.7282e-02, -1.5875e-02, -8.5772e-02,  7.5234e-02,  7.1847e-02,\n",
       "          -3.6529e-02, -8.5186e-03,  6.3485e-02, -9.0895e-02, -5.5118e-02],\n",
       "         [-8.1596e-02,  3.8411e-02, -6.6610e-02, -6.1558e-02,  1.9670e-02,\n",
       "           6.9351e-02, -8.9155e-03,  6.3550e-02,  5.9895e-02,  2.1424e-02,\n",
       "           4.1118e-02,  9.1094e-02, -2.7736e-02,  8.1240e-03,  1.4398e-02,\n",
       "           9.7167e-02, -3.9104e-02, -9.5713e-02,  1.3121e-03, -8.8523e-02,\n",
       "          -1.2473e-02,  5.7877e-02,  1.4470e-03, -1.2689e-02,  2.3604e-02,\n",
       "           5.7260e-02,  3.8752e-02, -6.1645e-02, -1.8199e-03, -1.9748e-02,\n",
       "           5.0584e-02,  4.5898e-02, -4.1178e-02, -7.3993e-02, -6.8745e-02,\n",
       "           4.6738e-02, -5.1452e-02,  8.0415e-02, -2.7645e-02, -8.5673e-02,\n",
       "           7.3269e-02,  8.9386e-02, -5.4324e-02, -5.1511e-02,  4.5373e-02,\n",
       "          -5.7996e-02, -7.4358e-02, -2.2037e-02, -4.2990e-02,  5.0791e-02,\n",
       "           4.1921e-03, -8.8275e-03,  1.6707e-02, -8.4835e-02,  8.9056e-02,\n",
       "           6.4489e-02,  3.1536e-02,  6.8311e-02,  7.2844e-02,  4.6869e-02,\n",
       "           1.9067e-02, -1.7585e-02,  1.9893e-03, -3.9057e-02,  1.0408e-02,\n",
       "           6.5925e-02,  6.6654e-02, -5.3823e-02, -6.9723e-02,  4.4347e-02,\n",
       "          -6.2607e-02,  7.2620e-02, -2.7706e-02,  3.3318e-03, -6.1779e-02,\n",
       "          -6.8898e-02,  8.6571e-02,  5.1460e-04, -7.4039e-02,  8.0482e-02,\n",
       "           2.0905e-02,  9.1448e-02,  4.1904e-03, -3.6425e-02,  5.7565e-02,\n",
       "          -2.5852e-02,  5.9746e-02, -9.1786e-02,  8.2261e-02, -5.1351e-02,\n",
       "           7.6269e-02,  7.7626e-02,  9.6908e-03, -9.0551e-02,  3.1625e-02,\n",
       "           1.1570e-02,  5.0752e-02, -3.8258e-02,  7.0819e-03,  9.3696e-02],\n",
       "         [-4.4970e-02, -1.0793e-02, -5.4032e-02,  6.0277e-02,  4.8496e-02,\n",
       "          -9.2428e-02, -8.7639e-02, -5.8615e-02, -8.2393e-02, -6.7750e-02,\n",
       "          -3.5982e-02, -5.0207e-02,  2.2522e-02,  3.9522e-02,  6.1507e-02,\n",
       "          -7.9907e-02,  7.4502e-02, -1.2297e-02, -2.6608e-02,  4.3699e-02,\n",
       "          -2.7802e-03,  2.6209e-02, -9.9079e-02, -4.0191e-02, -6.7594e-02,\n",
       "           9.9601e-02, -2.2375e-02, -9.0812e-02,  8.8218e-02,  9.3857e-03,\n",
       "           6.7994e-02,  1.2283e-02, -8.4394e-02, -9.7560e-02,  4.3318e-02,\n",
       "          -7.6539e-02, -1.2849e-02,  3.0886e-02,  7.0160e-02, -5.5070e-02,\n",
       "           3.8359e-02,  9.2806e-02,  4.0700e-02,  2.6191e-02,  7.5478e-02,\n",
       "          -5.9793e-02,  8.7335e-02,  8.1586e-02,  9.3762e-02,  8.5682e-02,\n",
       "          -8.7156e-03,  1.2763e-02,  9.0963e-02, -7.0422e-02, -9.2226e-02,\n",
       "          -9.1281e-02,  3.8354e-02,  5.2968e-03, -8.4656e-03,  4.5294e-02,\n",
       "           7.8447e-02,  3.2881e-02,  6.0091e-02,  4.6977e-02,  2.9791e-02,\n",
       "           8.0814e-02,  4.2019e-02, -2.5750e-02,  1.9534e-02, -6.1935e-02,\n",
       "           1.8228e-02,  3.4992e-02, -2.5479e-02, -4.8572e-02,  4.5101e-02,\n",
       "           2.6332e-02,  6.4385e-02, -5.4435e-02,  3.5828e-02, -4.7915e-02,\n",
       "           2.9050e-02,  2.7888e-02, -7.9056e-02,  2.7443e-02,  2.0072e-02,\n",
       "           2.7240e-02, -2.8174e-02,  1.4464e-02, -6.6526e-02, -5.6345e-02,\n",
       "           6.3077e-03, -8.4557e-02,  4.2590e-02, -7.7891e-02, -9.2599e-02,\n",
       "          -5.2267e-02,  3.4290e-02,  3.0541e-02,  8.8694e-02,  1.3981e-02]],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([-0.0464, -0.0544,  0.0866, -0.0306,  0.0739,  0.0407,  0.0819, -0.0011,\n",
       "         -0.0186, -0.0588], requires_grad=True)]"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 37
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-17T03:06:34.677508500Z",
     "start_time": "2024-07-17T03:06:34.619793100Z"
    }
   },
   "outputs": [],
   "source": [
    "# model.state_dict()  # 这种方法用于保存模型参数，看能看见参数属于模型的哪一部分"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:51:52.227685Z",
     "start_time": "2025-01-15T02:51:52.224900Z"
    }
   },
   "source": [
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss() #内部先做softmax，然后计算交叉熵\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package,随机梯度下降\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)"
   ],
   "outputs": [],
   "execution_count": 38
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T02:54:18.764007Z",
     "start_time": "2025-01-15T02:54:18.761382Z"
    }
   },
   "cell_type": "code",
   "source": "10000/32",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "312.5"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 39
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T03:12:38.201934Z",
     "start_time": "2025-01-15T03:12:37.782421Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad() # 装饰器，禁止反向传播，节省内存\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = [] # 记录损失\n",
    "    pred_list = [] # 记录预测\n",
    "    label_list = [] # 记录标签\n",
    "    for datas, labels in dataloader:#10000/32=312\n",
    "        datas = datas.to(device) # 转到GPU\n",
    "        labels = labels.to(device) # 转到GPU\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失,loss尺寸是一个数值\n",
    "        loss_list.append(loss.item()) # 记录损失,item是把tensor转换为数值\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测,argmax返回最大值索引\n",
    "        # print(preds)\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())#将PyTorch张量转换为NumPy数组。只有当张量在CPU上时，这个转换才是合法的\n",
    "        # print(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list) # 计算准确率\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 40
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "data": {
      "text/plain": "37500"
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1875*20"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-17T03:06:35.201490200Z",
     "start_time": "2024-07-17T03:06:35.194584600Z"
    }
   }
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T03:24:57.495521Z",
     "start_time": "2025-01-15T03:22:42.704387Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(model, train_loader, val_loader, epoch, loss_fct, optimizer, eval_step=500):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    #tqdm是一个进度条库\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar: # 进度条 1875*20,60000/32=1875\n",
    "        for epoch_id in range(epoch): # 训练epoch次\n",
    "            # training\n",
    "            for datas, labels in train_loader: #执行次数是60000/32=1875\n",
    "                datas = datas.to(device) #datas尺寸是[batch_size,1,28,28]\n",
    "                labels = labels.to(device) #labels尺寸是[batch_size]\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传，loss.backward()会计算梯度，loss对模型参数求导\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等,优化器的学习率会随着训练的进行而减小，更新w,b\n",
    "                optimizer.step() #梯度是计算并存储在模型参数的 .grad 属性中，优化器使用这些存储的梯度来更新模型参数\n",
    "\n",
    "                preds = logits.argmax(axis=-1) # 训练集预测\n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())   # 计算准确率，numpy可以\n",
    "                loss = loss.cpu().item() # 损失转到CPU，item()取值,一个数值\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                }) # 记录训练集信息，每一步的损失，准确率，步数\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval() # 进入评估模式\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train() # 进入训练模式\n",
    "\n",
    "                # udate step\n",
    "                global_step += 1 # 全局步数加1\n",
    "                pbar.update(1) # 更新进度条\n",
    "                pbar.set_postfix({\"epoch\": epoch_id}) # 设置进度条显示信息\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20 #改为40\n",
    "model = model.to(device)\n",
    "record = training(model, train_loader, val_loader, epoch, loss_fct, optimizer, eval_step=1000)"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/37500 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "733599c7c28c43b6a3fa82bcb6710b8b"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 41
  },
  {
   "cell_type": "code",
   "source": [
    "record[\"train\"][-5:]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T03:25:40.988961Z",
     "start_time": "2025-01-15T03:25:40.985855Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.25853797793388367, 'acc': 0.9375, 'step': 37495},\n",
       " {'loss': 0.2893495261669159, 'acc': 0.90625, 'step': 37496},\n",
       " {'loss': 0.533687174320221, 'acc': 0.875, 'step': 37497},\n",
       " {'loss': 0.25465649366378784, 'acc': 0.90625, 'step': 37498},\n",
       " {'loss': 0.2451382428407669, 'acc': 0.875, 'step': 37499}]"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 42
  },
  {
   "cell_type": "code",
   "source": [
    "record[\"val\"][-5:]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-15T03:25:47.520688Z",
     "start_time": "2025-01-15T03:25:47.517675Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.37195760058090327, 'acc': 0.8684, 'step': 33000},\n",
       " {'loss': 0.3622150492196837, 'acc': 0.8705, 'step': 34000},\n",
       " {'loss': 0.37430605804101347, 'acc': 0.8646, 'step': 35000},\n",
       " {'loss': 0.3646247967268331, 'acc': 0.8664, 'step': 36000},\n",
       " {'loss': 0.3705096992845543, 'acc': 0.8646, 'step': 37000}]"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 43
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-15T03:26:02.810428Z",
     "start_time": "2025-01-15T03:26:02.712170Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=1000):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "    last_step = train_df.index[-1] # 最后一步的步数\n",
    "    # print(train_df.columns)\n",
    "    print(train_df['acc'])\n",
    "    print(val_df['acc'])\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns) # 画几张图,分别是损失和准确率\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):\n",
    "        # print(train_df[item].values)\n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid() # 显示网格\n",
    "        axs[idx].legend() # 显示图例\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000)) # 设置x轴刻度\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, last_step, 5000))) # 设置x轴标签\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step\n",
      "0        0.03125\n",
      "1000     0.71875\n",
      "2000     0.75000\n",
      "3000     0.87500\n",
      "4000     0.78125\n",
      "5000     0.78125\n",
      "6000     0.81250\n",
      "7000     0.93750\n",
      "8000     0.87500\n",
      "9000     0.90625\n",
      "10000    0.84375\n",
      "11000    0.93750\n",
      "12000    0.84375\n",
      "13000    0.78125\n",
      "14000    0.87500\n",
      "15000    0.93750\n",
      "16000    0.81250\n",
      "17000    0.84375\n",
      "18000    0.71875\n",
      "19000    0.90625\n",
      "20000    0.78125\n",
      "21000    0.84375\n",
      "22000    0.87500\n",
      "23000    0.93750\n",
      "24000    0.84375\n",
      "25000    0.90625\n",
      "26000    0.93750\n",
      "27000    0.90625\n",
      "28000    0.90625\n",
      "29000    0.87500\n",
      "30000    0.93750\n",
      "31000    0.87500\n",
      "32000    0.93750\n",
      "33000    0.90625\n",
      "34000    0.96875\n",
      "35000    0.90625\n",
      "36000    0.90625\n",
      "37000    0.90625\n",
      "Name: acc, dtype: float64\n",
      "step\n",
      "0        0.0873\n",
      "1000     0.6938\n",
      "2000     0.7563\n",
      "3000     0.7923\n",
      "4000     0.8028\n",
      "5000     0.8235\n",
      "6000     0.8217\n",
      "7000     0.8300\n",
      "8000     0.8314\n",
      "9000     0.8347\n",
      "10000    0.8318\n",
      "11000    0.8421\n",
      "12000    0.8446\n",
      "13000    0.8449\n",
      "14000    0.8475\n",
      "15000    0.8477\n",
      "16000    0.8541\n",
      "17000    0.8552\n",
      "18000    0.8566\n",
      "19000    0.8572\n",
      "20000    0.8572\n",
      "21000    0.8629\n",
      "22000    0.8631\n",
      "23000    0.8589\n",
      "24000    0.8636\n",
      "25000    0.8670\n",
      "26000    0.8592\n",
      "27000    0.8624\n",
      "28000    0.8674\n",
      "29000    0.8677\n",
      "30000    0.8612\n",
      "31000    0.8502\n",
      "32000    0.8717\n",
      "33000    0.8684\n",
      "34000    0.8705\n",
      "35000    0.8646\n",
      "36000    0.8664\n",
      "37000    0.8646\n",
      "Name: acc, dtype: float64\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 44
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-17T03:17:16.674099900Z",
     "start_time": "2024-07-17T03:17:14.333157800Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3578\n",
      "accuracy: 0.8700\n"
     ]
    }
   ],
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "model.eval() # 进入评估模式\n",
    "loss, acc = evaluating(model, val_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
